From dbd2dd60604fbcb5456a864a37d9c1b5a9e6f231 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Wed, 18 Sep 2024 23:41:38 +0600 Subject: [PATCH] refactor(misconf): pass options to Rego scanner as is (#7529) Signed-off-by: nikpivkin --- pkg/iac/rego/load.go | 18 +- pkg/iac/rego/load_test.go | 49 ++- pkg/iac/rego/options.go | 108 ++++++ pkg/iac/rego/scanner.go | 93 ++---- pkg/iac/rego/scanner_test.go | 311 +++++++++--------- pkg/iac/scanners/azure/arm/scanner.go | 43 +-- pkg/iac/scanners/cloudformation/scanner.go | 44 +-- .../scanners/cloudformation/scanner_test.go | 9 +- .../cloudformation/test/cf_scanning_test.go | 6 +- pkg/iac/scanners/dockerfile/scanner.go | 79 +---- pkg/iac/scanners/dockerfile/scanner_test.go | 12 +- pkg/iac/scanners/helm/scanner.go | 75 +---- pkg/iac/scanners/helm/test/scanner_test.go | 32 +- pkg/iac/scanners/json/scanner.go | 69 +--- pkg/iac/scanners/json/scanner_test.go | 4 +- pkg/iac/scanners/kubernetes/scanner.go | 68 +--- pkg/iac/scanners/kubernetes/scanner_test.go | 40 +-- pkg/iac/scanners/options/scanner.go | 102 +----- pkg/iac/scanners/terraform/fs_test.go | 6 +- pkg/iac/scanners/terraform/ignore_test.go | 9 +- pkg/iac/scanners/terraform/scanner.go | 72 +--- .../terraform/scanner_integration_test.go | 35 +- pkg/iac/scanners/terraform/scanner_test.go | 85 ++--- pkg/iac/scanners/terraform/setup_test.go | 5 +- .../terraformplan/snapshot/scanner_test.go | 25 +- .../scanners/terraformplan/tfjson/scanner.go | 85 +---- .../terraformplan/tfjson/scanner_test.go | 17 +- .../terraformplan/tfjson/test/scanner_test.go | 6 +- pkg/iac/scanners/toml/scanner.go | 65 +--- pkg/iac/scanners/toml/scanner_test.go | 4 +- pkg/iac/scanners/yaml/scanner.go | 64 +--- pkg/iac/scanners/yaml/scanner_test.go | 4 +- pkg/misconf/scanner.go | 21 +- 33 files changed, 570 insertions(+), 1095 deletions(-) create mode 100644 pkg/iac/rego/options.go diff --git a/pkg/iac/rego/load.go b/pkg/iac/rego/load.go index 26a6c9e6f2d1..a1c29d163fae 100644 --- a/pkg/iac/rego/load.go +++ b/pkg/iac/rego/load.go @@ -75,7 +75,7 @@ func (s *Scanner) loadEmbedded() error { return nil } -func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies bool, srcFS fs.FS, paths []string, readers []io.Reader) error { +func (s *Scanner) LoadPolicies(srcFS fs.FS) error { if s.policies == nil { s.policies = make(map[string]*ast.Module) @@ -90,19 +90,19 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b return err } - if enableEmbeddedPolicies { + if s.includeEmbeddedPolicies { s.policies = lo.Assign(s.policies, s.embeddedChecks) } - if enableEmbeddedLibraries { + if s.includeEmbeddedLibraries { s.policies = lo.Assign(s.policies, s.embeddedLibs) } var err error - if len(paths) > 0 { - loaded, err := LoadPoliciesFromDirs(srcFS, paths...) + if len(s.policyDirs) > 0 { + loaded, err := LoadPoliciesFromDirs(srcFS, s.policyDirs...) if err != nil { - return fmt.Errorf("failed to load rego checks from %s: %w", paths, err) + return fmt.Errorf("failed to load rego checks from %s: %w", s.policyDirs, err) } for name, policy := range loaded { s.policies[name] = policy @@ -110,8 +110,8 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b s.logger.Debug("Checks from disk are loaded", log.Int("count", len(loaded))) } - if len(readers) > 0 { - loaded, err := s.loadPoliciesFromReaders(readers) + if len(s.policyReaders) > 0 { + loaded, err := s.loadPoliciesFromReaders(s.policyReaders) if err != nil { return fmt.Errorf("failed to load rego checks from reader(s): %w", err) } @@ -143,7 +143,7 @@ func (s *Scanner) LoadPolicies(enableEmbeddedLibraries, enableEmbeddedPolicies b } s.store = store - return s.compilePolicies(srcFS, paths) + return s.compilePolicies(srcFS, s.policyDirs) } func (s *Scanner) fallbackChecks(compiler *ast.Compiler) { diff --git a/pkg/iac/rego/load_test.go b/pkg/iac/rego/load_test.go index e0c136562d45..174cbc732525 100644 --- a/pkg/iac/rego/load_test.go +++ b/pkg/iac/rego/load_test.go @@ -4,7 +4,6 @@ import ( "bytes" "embed" "fmt" - "io" "log/slog" "strings" "testing" @@ -16,7 +15,6 @@ import ( checks "github.com/aquasecurity/trivy-checks" "github.com/aquasecurity/trivy/pkg/iac/rego" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/types" "github.com/aquasecurity/trivy/pkg/log" ) @@ -33,10 +31,11 @@ func Test_RegoScanning_WithSomeInvalidPolicies(t *testing.T) { slog.SetDefault(log.New(log.NewHandler(&debugBuf, nil))) scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithRegoErrorLimits(0), + rego.WithRegoErrorLimits(0), + rego.WithPolicyDirs("."), ) - err := scanner.LoadPolicies(false, false, testEmbedFS, []string{"."}, nil) + err := scanner.LoadPolicies(testEmbedFS) require.ErrorContains(t, err, `want (one of): ["Cmd" "EndLine" "Flags" "JSON" "Original" "Path" "Stage" "StartLine" "SubCmd" "Value"]`) assert.Contains(t, debugBuf.String(), "Error(s) occurred while loading checks") }) @@ -46,10 +45,11 @@ func Test_RegoScanning_WithSomeInvalidPolicies(t *testing.T) { slog.SetDefault(log.New(log.NewHandler(&debugBuf, nil))) scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithRegoErrorLimits(1), + rego.WithRegoErrorLimits(1), + rego.WithPolicyDirs("."), ) - err := scanner.LoadPolicies(false, false, testEmbedFS, []string{"."}, nil) + err := scanner.LoadPolicies(testEmbedFS) require.NoError(t, err) assert.Contains(t, debugBuf.String(), "Error occurred while parsing\tfile_path=\"testdata/policies/invalid.rego\" err=\"testdata/policies/invalid.rego:7") @@ -64,9 +64,13 @@ package mypackage deny { input.evil == "foo bar" }` - scanner := rego.NewScanner(types.SourceJSON) + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("."), + rego.WithPolicyReader(strings.NewReader(check)), + ) - err := scanner.LoadPolicies(false, false, fstest.MapFS{}, []string{"."}, []io.Reader{strings.NewReader(check)}) + err := scanner.LoadPolicies(fstest.MapFS{}) assert.ErrorContains(t, err, "could not find schema \"fooschema\"") }) @@ -79,7 +83,11 @@ package mypackage deny { input.evil == "foo bar" }` - scanner := rego.NewScanner(types.SourceJSON) + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("."), + rego.WithPolicyReader(strings.NewReader(check)), + ) fsys := fstest.MapFS{ "schemas/fooschema.json": &fstest.MapFile{ @@ -87,7 +95,7 @@ deny { }, } - err := scanner.LoadPolicies(false, false, fsys, []string{"."}, []io.Reader{strings.NewReader(check)}) + err := scanner.LoadPolicies(fsys) assert.ErrorContains(t, err, "could not parse schema \"fooschema\"") }) @@ -97,8 +105,12 @@ deny { deny { input.evil == "foo bar" }` - scanner := rego.NewScanner(types.SourceJSON) - err := scanner.LoadPolicies(false, false, fstest.MapFS{}, []string{"."}, []io.Reader{strings.NewReader(check)}) + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("."), + rego.WithPolicyReader(strings.NewReader(check)), + ) + err := scanner.LoadPolicies(fstest.MapFS{}) require.NoError(t, err) }) @@ -184,8 +196,9 @@ deny { t.Run(tt.name, func(t *testing.T) { scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithRegoErrorLimits(0), - options.ScannerWithEmbeddedPolicies(false), + rego.WithRegoErrorLimits(0), + rego.WithEmbeddedPolicies(false), + rego.WithPolicyDirs("."), ) tt.files["schemas/fooschema.json"] = &fstest.MapFile{ @@ -200,9 +213,8 @@ deny { }`), } - fsys := fstest.MapFS(tt.files) checks.EmbeddedPolicyFileSystem = embeddedChecksFS - err := scanner.LoadPolicies(false, false, fsys, []string{"."}, nil) + err := scanner.LoadPolicies(fstest.MapFS(tt.files)) if tt.expectedErr != "" { assert.ErrorContains(t, err, tt.expectedErr) @@ -244,8 +256,9 @@ deny { scanner := rego.NewScanner( types.SourceDockerfile, - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedPolicies(false), + rego.WithPolicyDirs("."), ) - err := scanner.LoadPolicies(false, false, fsys, []string{"."}, nil) + err := scanner.LoadPolicies(fsys) require.Error(t, err) } diff --git a/pkg/iac/rego/options.go b/pkg/iac/rego/options.go new file mode 100644 index 000000000000..d4b622a68c16 --- /dev/null +++ b/pkg/iac/rego/options.go @@ -0,0 +1,108 @@ +package rego + +import ( + "io" + "io/fs" + + "github.com/aquasecurity/trivy/pkg/iac/scanners/options" +) + +func WithPolicyReader(readers ...io.Reader) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.policyReaders = readers + } + } +} + +func WithEmbeddedPolicies(include bool) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.includeEmbeddedPolicies = include + } + } +} + +func WithEmbeddedLibraries(include bool) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.includeEmbeddedLibraries = include + } + } +} + +// WithTrace specifies an io.Writer for trace logs (mainly rego tracing) - if not set, they are discarded +func WithTrace(w io.Writer) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.traceWriter = w + } + } +} + +func WithPerResultTracing(enabled bool) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.tracePerResult = enabled + } + } +} + +func WithPolicyDirs(paths ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.policyDirs = paths + } + } +} + +func WithDataDirs(paths ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.dataDirs = paths + } + } +} + +// WithPolicyNamespaces - namespaces which indicate rego policies containing enforced rules +func WithPolicyNamespaces(namespaces ...string) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + for _, namespace := range namespaces { + ss.ruleNamespaces[namespace] = struct{}{} + } + } + } +} + +func WithPolicyFilesystem(fsys fs.FS) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.policyFS = fsys + } + } +} + +func WithDataFilesystem(fsys fs.FS) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.dataFS = fsys + } + } +} + +func WithRegoErrorLimits(limit int) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.regoErrorLimit = limit + } + } +} + +func WithCustomSchemas(schemas map[string][]byte) options.ScannerOption { + return func(s options.ConfigurableScanner) { + if ss, ok := s.(*Scanner); ok { + ss.customSchemas = schemas + } + } +} diff --git a/pkg/iac/rego/scanner.go b/pkg/iac/rego/scanner.go index f6108ffefd66..a8e1caf525b3 100644 --- a/pkg/iac/rego/scanner.go +++ b/pkg/iac/rego/scanner.go @@ -44,24 +44,27 @@ func makeSupportedProviders() map[string]struct{} { var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - ruleNamespaces map[string]struct{} - policies map[string]*ast.Module - store storage.Store - dataDirs []string - runtimeValues *ast.Term - compiler *ast.Compiler - regoErrorLimit int - logger *log.Logger - traceWriter io.Writer - tracePerResult bool - retriever *MetadataRetriever - policyFS fs.FS - dataFS fs.FS - frameworks []framework.Framework - spec string - inputSchema any // unmarshalled into this from a json schema document - sourceType types.Source - includeDeprecatedChecks bool + ruleNamespaces map[string]struct{} + policies map[string]*ast.Module + store storage.Store + runtimeValues *ast.Term + compiler *ast.Compiler + regoErrorLimit int + logger *log.Logger + traceWriter io.Writer + tracePerResult bool + retriever *MetadataRetriever + policyFS fs.FS + policyDirs []string + policyReaders []io.Reader + dataFS fs.FS + dataDirs []string + frameworks []framework.Framework + inputSchema any // unmarshalled into this from a json schema document + sourceType types.Source + includeDeprecatedChecks bool + includeEmbeddedPolicies bool + includeEmbeddedLibraries bool embeddedLibs map[string]*ast.Module embeddedChecks map[string]*ast.Module @@ -72,24 +75,12 @@ func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.includeDeprecatedChecks = b } -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - // handled externally -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - func (s *Scanner) SetRegoOnly(bool) {} func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { s.frameworks = frameworks } -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - // handled externally -} - func (s *Scanner) trace(heading string, input any) { if s.traceWriter == nil { return @@ -101,48 +92,6 @@ func (s *Scanner) trace(heading string, input any) { _, _ = fmt.Fprintf(s.traceWriter, "REGO %[1]s:\n%s\nEND REGO %[1]s\n\n", heading, string(data)) } -func (s *Scanner) SetPolicyFilesystem(fsys fs.FS) { - s.policyFS = fsys -} - -func (s *Scanner) SetDataFilesystem(fsys fs.FS) { - s.dataFS = fsys -} - -func (s *Scanner) SetPolicyReaders(_ []io.Reader) { - // NOTE: Policy readers option not applicable for rego, policies are loaded on-demand by other scanners. -} - -func (s *Scanner) SetTraceWriter(writer io.Writer) { - s.traceWriter = writer -} - -func (s *Scanner) SetPerResultTracingEnabled(b bool) { - s.tracePerResult = b -} - -func (s *Scanner) SetPolicyDirs(_ ...string) { - // NOTE: Policy dirs option not applicable for rego, policies are loaded on-demand by other scanners. -} - -func (s *Scanner) SetDataDirs(dirs ...string) { - s.dataDirs = dirs -} - -func (s *Scanner) SetPolicyNamespaces(namespaces ...string) { - for _, namespace := range namespaces { - s.ruleNamespaces[namespace] = struct{}{} - } -} - -func (s *Scanner) SetRegoErrorLimit(limit int) { - s.regoErrorLimit = limit -} - -func (s *Scanner) SetCustomSchemas(v map[string][]byte) { - s.customSchemas = v -} - type DynamicMetadata struct { Warning bool Filepath string diff --git a/pkg/iac/rego/scanner_test.go b/pkg/iac/rego/scanner_test.go index c453cc984b1c..73ef55223f14 100644 --- a/pkg/iac/rego/scanner_test.go +++ b/pkg/iac/rego/scanner_test.go @@ -1,9 +1,8 @@ -package rego +package rego_test import ( "bytes" "context" - "io" "io/fs" "os" "path/filepath" @@ -15,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/severity" "github.com/aquasecurity/trivy/pkg/iac/types" ) @@ -44,13 +43,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -79,13 +78,13 @@ deny { srcFS := os.DirFS(tmp) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"/policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -114,13 +113,13 @@ warn { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -146,13 +145,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": false, @@ -189,13 +188,13 @@ exception[ns] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -237,13 +236,13 @@ exception[ns] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -274,13 +273,13 @@ exception[rules] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -310,13 +309,13 @@ exception[rules] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -344,13 +343,13 @@ deny_evil { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -375,13 +374,13 @@ deny[msg] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -413,13 +412,13 @@ deny[res] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -455,13 +454,13 @@ deny[res] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -509,13 +508,13 @@ deny[res] { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -558,13 +557,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -592,13 +591,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -623,13 +622,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -658,13 +657,14 @@ deny { traceBuffer := bytes.NewBuffer([]byte{}) - scanner := NewScanner(types.SourceJSON, options.ScannerWithTrace(traceBuffer)) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithTrace(traceBuffer), + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -692,13 +692,14 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON, options.ScannerWithPerResultTracing(true)) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPerResultTracing(true), + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "evil": true, @@ -730,13 +731,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "dynamic", @@ -763,13 +764,13 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "test", @@ -810,13 +811,14 @@ deny { `, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithPerResultTracing(true), + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "test", @@ -848,13 +850,11 @@ deny { `, }) - scanner := NewScanner(types.SourceDockerfile) - scanner.SetRegoErrorLimit(0) // override to not allow any errors - assert.ErrorContains( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), - "undefined ref: input.evil", + scanner := rego.NewScanner( + types.SourceDockerfile, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) } func Test_RegoScanning_WithValidInputSchema(t *testing.T) { @@ -871,11 +871,11 @@ deny { `, }) - scanner := NewScanner(types.SourceDockerfile) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceDockerfile, + rego.WithPolicyDirs("policies"), ) + require.NoError(t, scanner.LoadPolicies(srcFS)) } func Test_RegoScanning_WithFilepathToSchema(t *testing.T) { @@ -890,11 +890,16 @@ deny { } `, }) - scanner := NewScanner(types.SourceJSON) - scanner.SetRegoErrorLimit(0) // override to not allow any errors + + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithRegoErrorLimits(0), + rego.WithPolicyDirs("policies"), + ) + assert.ErrorContains( t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner.LoadPolicies(srcFS), "undefined ref: input.evil", ) } @@ -922,16 +927,16 @@ deny { "data/junk.txt": "this file should be ignored", }) - scanner := NewScanner(types.SourceJSON) - scanner.SetDataFilesystem(dataFS) - scanner.SetDataDirs(".") - - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithDataFilesystem(dataFS), + rego.WithDataDirs("."), + rego.WithPolicyDirs("policies"), ) - results, err := scanner.ScanInput(context.TODO(), Input{}) + require.NoError(t, scanner.LoadPolicies(srcFS)) + + results, err := scanner.ScanInput(context.TODO(), rego.Input{}) require.NoError(t, err) assert.Len(t, results.GetFailed(), 1) @@ -962,16 +967,16 @@ deny { "data/junk.txt": "this file should be ignored", }) - scanner := NewScanner(types.SourceJSON) - scanner.SetDataFilesystem(dataFS) - scanner.SetDataDirs("X://") - - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), + scanner := rego.NewScanner( + types.SourceJSON, + rego.WithDataFilesystem(dataFS), + rego.WithDataDirs("X://"), + rego.WithPolicyDirs("policies"), ) - results, err := scanner.ScanInput(context.TODO(), Input{}) + require.NoError(t, scanner.LoadPolicies(srcFS)) + + results, err := scanner.ScanInput(context.TODO(), rego.Input{}) require.NoError(t, err) assert.Len(t, results.GetFailed(), 1) @@ -998,14 +1003,12 @@ deny { }, } - scanner := NewScanner( + scanner := rego.NewScanner( types.SourceYAML, + rego.WithPolicyDirs("checks"), ) - require.NoError( - t, - scanner.LoadPolicies(false, false, fsys, []string{"checks"}, nil), - ) - _, err := scanner.ScanInput(context.TODO(), Input{}) + require.NoError(t, scanner.LoadPolicies(fsys)) + _, err := scanner.ScanInput(context.TODO(), rego.Input{}) require.NoError(t, err) } @@ -1066,13 +1069,10 @@ deny { "policies/test.rego": tc.policy, }) - scanner := NewScanner(types.SourceJSON) - require.NoError( - t, - scanner.LoadPolicies(false, false, srcFS, []string{"policies"}, nil), - ) + scanner := rego.NewScanner(types.SourceJSON, rego.WithPolicyDirs("policies")) + require.NoError(t, scanner.LoadPolicies(srcFS)) - results, err := scanner.ScanInput(context.TODO(), Input{ + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "/evil.lol", Contents: map[string]any{ "text": "test", @@ -1133,17 +1133,18 @@ deny { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - scanner := NewScanner( + scanner := rego.NewScanner( types.SourceYAML, - options.ScannerWithCustomSchemas(map[string][]byte{ + rego.WithCustomSchemas(map[string][]byte{ "test": []byte(schema), }), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(tc.check)), ) - err := scanner.LoadPolicies(false, false, nil, nil, []io.Reader{strings.NewReader(tc.check)}) - require.NoError(t, err) - results, err := scanner.ScanInput(context.TODO(), Input{ + require.NoError(t, scanner.LoadPolicies(nil)) + + results, err := scanner.ScanInput(context.TODO(), rego.Input{ Path: "test.yaml", Contents: map[string]any{"service": "test"}, }) diff --git a/pkg/iac/scanners/azure/arm/scanner.go b/pkg/iac/scanners/azure/arm/scanner.go index e4b3258f823f..410ccd6d18df 100644 --- a/pkg/iac/scanners/azure/arm/scanner.go +++ b/pkg/iac/scanners/azure/arm/scanner.go @@ -3,7 +3,6 @@ package arm import ( "context" "fmt" - "io" "io/fs" "sync" @@ -30,12 +29,7 @@ type Scanner struct { logger *log.Logger frameworks []framework.Framework regoOnly bool - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool - policyDirs []string - policyReaders []io.Reader regoScanner *rego.Scanner - spec string includeDeprecatedChecks bool } @@ -43,12 +37,6 @@ func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.includeDeprecatedChecks = b } -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - func (s *Scanner) SetRegoOnly(regoOnly bool) { s.regoOnly = regoOnly } @@ -68,39 +56,10 @@ func (s *Scanner) Name() string { return "Azure ARM" } -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { s.frameworks = frameworks } -func (s *Scanner) SetTraceWriter(io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(bool) {} -func (s *Scanner) SetDataDirs(...string) {} -func (s *Scanner) SetPolicyNamespaces(...string) {} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func (s *Scanner) initRegoScanner(srcFS fs.FS) error { s.mu.Lock() defer s.mu.Unlock() @@ -108,7 +67,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) error { return nil } regoScanner := rego.NewScanner(types.SourceCloud, s.scannerOptions...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/cloudformation/scanner.go b/pkg/iac/scanners/cloudformation/scanner.go index dc4deab0aff5..4497a807506c 100644 --- a/pkg/iac/scanners/cloudformation/scanner.go +++ b/pkg/iac/scanners/cloudformation/scanner.go @@ -3,7 +3,6 @@ package cloudformation import ( "context" "fmt" - "io" "io/fs" "sort" "sync" @@ -50,17 +49,12 @@ var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { mu sync.Mutex logger *log.Logger - policyDirs []string - policyReaders []io.Reader parser *parser.Parser regoScanner *rego.Scanner regoOnly bool - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool options []options.ScannerOption parserOptions []parser.Option frameworks []framework.Framework - spec string includeDeprecatedChecks bool } @@ -68,8 +62,6 @@ func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.includeDeprecatedChecks = b } -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - func (s *Scanner) addParserOption(opt parser.Option) { s.parserOptions = append(s.parserOptions, opt) } @@ -78,18 +70,6 @@ func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { s.frameworks = frameworks } -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - func (s *Scanner) SetRegoOnly(regoOnly bool) { s.regoOnly = regoOnly } @@ -98,28 +78,6 @@ func (s *Scanner) Name() string { return "CloudFormation" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - -func (s *Scanner) SetTraceWriter(_ io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(_ bool) {} -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - // New creates a new Scanner func New(opts ...options.ScannerOption) *Scanner { s := &Scanner{ @@ -140,7 +98,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceCloud, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/cloudformation/scanner_test.go b/pkg/iac/scanners/cloudformation/scanner_test.go index 21d185c5ec06..67ee92cf69c3 100644 --- a/pkg/iac/scanners/cloudformation/scanner_test.go +++ b/pkg/iac/scanners/cloudformation/scanner_test.go @@ -10,6 +10,7 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) @@ -57,7 +58,7 @@ deny[res] { `, }) - scanner := New(options.ScannerWithPolicyDirs("rules"), options.ScannerWithRegoOnly(true)) + scanner := New(rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true)) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) @@ -215,9 +216,9 @@ Resources: scanner := New( options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithPolicyReader(strings.NewReader(bucketNameCheck)), - options.ScannerWithPolicyNamespaces("user"), + rego.WithEmbeddedPolicies(false), + rego.WithPolicyReader(strings.NewReader(bucketNameCheck)), + rego.WithPolicyNamespaces("user"), ) results, err := scanner.ScanFS(context.TODO(), fsys, "code") diff --git a/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go b/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go index 396963447ca9..46eed857a75f 100644 --- a/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go +++ b/pkg/iac/scanners/cloudformation/test/cf_scanning_test.go @@ -8,12 +8,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/cloudformation" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_basic_cloudformation_scanning(t *testing.T) { - cfScanner := cloudformation.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + cfScanner := cloudformation.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) results, err := cfScanner.ScanFS(context.TODO(), os.DirFS("./examples/bucket"), ".") require.NoError(t, err) @@ -22,7 +22,7 @@ func Test_basic_cloudformation_scanning(t *testing.T) { } func Test_cloudformation_scanning_has_expected_errors(t *testing.T) { - cfScanner := cloudformation.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + cfScanner := cloudformation.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) results, err := cfScanner.ScanFS(context.TODO(), os.DirFS("./examples/bucket"), ".") require.NoError(t, err) diff --git a/pkg/iac/scanners/dockerfile/scanner.go b/pkg/iac/scanners/dockerfile/scanner.go index e0d6ebd9ebde..1694f28d814a 100644 --- a/pkg/iac/scanners/dockerfile/scanner.go +++ b/pkg/iac/scanners/dockerfile/scanner.go @@ -2,7 +2,6 @@ package dockerfile import ( "context" - "io" "io/fs" "sync" @@ -20,81 +19,21 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - options []options.ScannerOption - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool + mu sync.Mutex + logger *log.Logger + parser *parser.Parser + regoScanner *rego.Scanner + options []options.ScannerOption } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(bool) { -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func (s *Scanner) Name() string { return "Dockerfile" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyNamespaces(_ ...string) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetRegoErrorLimit(_ int) { - // handled by rego when option is passed on -} - func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ options: opts, @@ -154,7 +93,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { } regoScanner := rego.NewScanner(types.SourceDockerfile, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/dockerfile/scanner_test.go b/pkg/iac/scanners/dockerfile/scanner_test.go index 4cbd86667a17..2872df1e4ef6 100644 --- a/pkg/iac/scanners/dockerfile/scanner_test.go +++ b/pkg/iac/scanners/dockerfile/scanner_test.go @@ -10,9 +10,9 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rego/schemas" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) const DS006PolicyWithDockerfileSchema = `# METADATA @@ -219,7 +219,7 @@ USER root "/rules/rule.rego": DS006LegacyWithOldStyleMetadata, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) @@ -564,10 +564,10 @@ COPY --from=dep /binary /` var traceBuf bytes.Buffer scanner := NewScanner( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithTrace(&traceBuf), - options.ScannerWithRegoErrorLimits(0), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedLibraries(true), + rego.WithTrace(&traceBuf), + rego.WithRegoErrorLimits(0), ) results, err := scanner.ScanFS(context.TODO(), fsys, "code") diff --git a/pkg/iac/scanners/helm/scanner.go b/pkg/iac/scanners/helm/scanner.go index 305a116b56b7..bfa63a5d2c00 100644 --- a/pkg/iac/scanners/helm/scanner.go +++ b/pkg/iac/scanners/helm/scanner.go @@ -27,34 +27,16 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - policyDirs []string - dataDirs []string - logger *log.Logger - options []options.ScannerOption - parserOptions []parser.Option - policyReaders []io.Reader - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool - policyFS fs.FS - frameworks []framework.Framework - spec string - regoScanner *rego.Scanner - mu sync.Mutex + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + parserOptions []parser.Option + regoScanner *rego.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(bool) { -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} // New creates a new Scanner func New(opts ...options.ScannerOption) *Scanner { @@ -73,49 +55,10 @@ func (s *Scanner) addParserOptions(opts ...parser.Option) { s.parserOptions = append(s.parserOptions, opts...) } -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - func (s *Scanner) Name() string { return "Helm" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(dirs ...string) { - s.dataDirs = dirs -} - -func (s *Scanner) SetPolicyNamespaces(namespaces ...string) { - // handled by rego later - nothing to do for now... -} - -func (s *Scanner) SetPolicyFilesystem(policyFS fs.FS) { - s.policyFS = policyFS -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) {} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func (s *Scanner) ScanFS(ctx context.Context, target fs.FS, path string) (scan.Results, error) { if err := s.initRegoScanner(target); err != nil { @@ -228,7 +171,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) error { return nil } regoScanner := rego.NewScanner(types.SourceKubernetes, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/helm/test/scanner_test.go b/pkg/iac/scanners/helm/test/scanner_test.go index 45a426762439..ef751ac2a7b8 100644 --- a/pkg/iac/scanners/helm/test/scanner_test.go +++ b/pkg/iac/scanners/helm/test/scanner_test.go @@ -13,8 +13,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/helm" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_helm_scanner_with_archive(t *testing.T) { @@ -40,7 +40,7 @@ func Test_helm_scanner_with_archive(t *testing.T) { for _, test := range tests { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testTemp := t.TempDir() testFileName := filepath.Join(testTemp, test.archiveName) @@ -96,7 +96,7 @@ func Test_helm_scanner_with_missing_name_can_recover(t *testing.T) { for _, test := range tests { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testTemp := t.TempDir() testFileName := filepath.Join(testTemp, test.archiveName) @@ -128,7 +128,7 @@ func Test_helm_scanner_with_dir(t *testing.T) { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testFs := os.DirFS(filepath.Join("testdata", test.chartName)) results, err := helmScanner.ScanFS(context.TODO(), testFs, ".") @@ -209,9 +209,9 @@ deny[res] { t.Run(test.testName, func(t *testing.T) { t.Logf("Running test: %s", test.testName) - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyNamespaces("user")) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + rego.WithPolicyDirs("rules"), + rego.WithPolicyNamespaces("user")) testTemp := t.TempDir() testFileName := filepath.Join(testTemp, test.archiveName) @@ -274,7 +274,7 @@ func copyArchive(src, dst string) error { } func Test_helm_chart_with_templated_name(t *testing.T) { - helmScanner := helm.New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + helmScanner := helm.New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) testFs := os.DirFS(filepath.Join("testdata", "templated-name")) _, err := helmScanner.ScanFS(context.TODO(), testFs, ".") require.NoError(t, err) @@ -302,10 +302,10 @@ deny[res] { } ` helmScanner := helm.New( - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyReader(strings.NewReader(policy)), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(policy)), ) results, err := helmScanner.ScanFS(context.TODO(), os.DirFS("testdata/simmilar-templates"), ".") @@ -348,10 +348,10 @@ deny[res] { ` scanner := helm.New( - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyReader(strings.NewReader(check)), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(check)), ) results, err := scanner.ScanFS(context.TODO(), os.DirFS("testdata/with-subchart"), ".") diff --git a/pkg/iac/scanners/json/scanner.go b/pkg/iac/scanners/json/scanner.go index 8991120be26f..f46f9cc56bc9 100644 --- a/pkg/iac/scanners/json/scanner.go +++ b/pkg/iac/scanners/json/scanner.go @@ -2,7 +2,6 @@ package json import ( "context" - "io" "io/fs" "sync" @@ -20,66 +19,16 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - options []options.ScannerOption - frameworks []framework.Framework - spec string - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool + mu sync.Mutex + logger *log.Logger + parser *parser.Parser + regoScanner *rego.Scanner + options []options.ScannerOption } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetRegoOnly(bool) { -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ @@ -143,7 +92,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceJSON, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/json/scanner_test.go b/pkg/iac/scanners/json/scanner_test.go index e126768e55d8..6656f70b2e25 100644 --- a/pkg/iac/scanners/json/scanner_test.go +++ b/pkg/iac/scanners/json/scanner_test.go @@ -9,8 +9,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan(t *testing.T) { @@ -48,7 +48,7 @@ deny[res] { `, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) diff --git a/pkg/iac/scanners/kubernetes/scanner.go b/pkg/iac/scanners/kubernetes/scanner.go index e9e9eacd73e8..dfd248cc8b1d 100644 --- a/pkg/iac/scanners/kubernetes/scanner.go +++ b/pkg/iac/scanners/kubernetes/scanner.go @@ -24,66 +24,16 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - policyDirs []string - policyReaders []io.Reader - regoScanner *rego.Scanner - parser *parser.Parser - loadEmbeddedPolicies bool - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + regoScanner *rego.Scanner + parser *parser.Parser } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(bool) {} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) { -} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ @@ -108,7 +58,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceKubernetes, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/kubernetes/scanner_test.go b/pkg/iac/scanners/kubernetes/scanner_test.go index c981634a0ee6..ef1ac38560f4 100644 --- a/pkg/iac/scanners/kubernetes/scanner_test.go +++ b/pkg/iac/scanners/kubernetes/scanner_test.go @@ -11,8 +11,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan_YAML(t *testing.T) { @@ -94,8 +94,8 @@ deny[res] { }) scanner := NewScanner( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedLibraries(true), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -256,8 +256,8 @@ deny[res] { }) scanner := NewScanner( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedLibraries(true), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -330,7 +330,7 @@ deny[res] { func Test_FileScan(t *testing.T) { - results, err := NewScanner(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), options.ScannerWithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` + results, err := NewScanner(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` apiVersion: v1 kind: Pod metadata: @@ -348,7 +348,7 @@ spec: func Test_FileScan_WithSeparator(t *testing.T) { - results, err := NewScanner(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` + results, err := NewScanner(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(` --- --- apiVersion: v1 @@ -391,9 +391,9 @@ spec: ` results, err := NewScanner( - options.ScannerWithEmbeddedPolicies(true), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(file)) + rego.WithEmbeddedPolicies(true), + rego.WithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true)).ScanReader(context.TODO(), "k8s.yaml", strings.NewReader(file)) require.NoError(t, err) assert.Greater(t, len(results.GetFailed()), 1) @@ -411,7 +411,7 @@ spec: func Test_FileScanWithPolicyReader(t *testing.T) { - results, err := NewScanner(options.ScannerWithPolicyReader(strings.NewReader(`package defsec + results, err := NewScanner(rego.WithPolicyReader(strings.NewReader(`package defsec deny[msg] { msg = "fail" @@ -434,7 +434,7 @@ spec: func Test_FileScanJSON(t *testing.T) { - results, err := NewScanner(options.ScannerWithPolicyReader(strings.NewReader(`package defsec + results, err := NewScanner(rego.WithPolicyReader(strings.NewReader(`package defsec deny[msg] { input.kind == "Pod" @@ -490,8 +490,8 @@ deny[msg] { func Test_FileScanWithMetadata(t *testing.T) { results, err := NewScanner( - options.ScannerWithTrace(os.Stdout), - options.ScannerWithPolicyReader(strings.NewReader(`package defsec + rego.WithTrace(os.Stdout), + rego.WithPolicyReader(strings.NewReader(`package defsec deny[msg] { input.kind == "Pod" @@ -529,8 +529,8 @@ spec: func Test_FileScanExampleWithResultFunction(t *testing.T) { results, err := NewScanner( - options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyReader(strings.NewReader(`package defsec + rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + rego.WithPolicyReader(strings.NewReader(`package defsec import data.lib.kubernetes @@ -707,10 +707,10 @@ spec: }) scanner := NewScanner( - // options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyDirs("policies/"), - options.ScannerWithPolicyFilesystem(srcFS), + // rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), + rego.WithPolicyDirs("policies/"), + rego.WithPolicyFilesystem(srcFS), ) results, err := scanner.ScanFS(context.TODO(), srcFS, "test/KSV001") require.NoError(t, err) diff --git a/pkg/iac/scanners/options/scanner.go b/pkg/iac/scanners/options/scanner.go index 4f07c4d14b0a..a9561d95130a 100644 --- a/pkg/iac/scanners/options/scanner.go +++ b/pkg/iac/scanners/options/scanner.go @@ -1,61 +1,13 @@ package options import ( - "io" - "io/fs" - "github.com/aquasecurity/trivy/pkg/iac/framework" ) type ConfigurableScanner interface { - SetTraceWriter(io.Writer) - SetPerResultTracingEnabled(bool) - SetPolicyDirs(...string) - SetDataDirs(...string) - SetPolicyNamespaces(...string) - SetPolicyReaders([]io.Reader) - SetPolicyFilesystem(fs.FS) - SetDataFilesystem(fs.FS) - SetUseEmbeddedPolicies(bool) SetFrameworks(frameworks []framework.Framework) - SetSpec(spec string) SetRegoOnly(regoOnly bool) - SetRegoErrorLimit(limit int) - SetUseEmbeddedLibraries(bool) SetIncludeDeprecatedChecks(bool) - SetCustomSchemas(map[string][]byte) -} - -type ScannerOption func(s ConfigurableScanner) - -func ScannerWithFrameworks(frameworks ...framework.Framework) ScannerOption { - return func(s ConfigurableScanner) { - s.SetFrameworks(frameworks) - } -} - -func ScannerWithSpec(spec string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetSpec(spec) - } -} - -func ScannerWithPolicyReader(readers ...io.Reader) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyReaders(readers) - } -} - -func ScannerWithEmbeddedPolicies(embedded bool) ScannerOption { - return func(s ConfigurableScanner) { - s.SetUseEmbeddedPolicies(embedded) - } -} - -func ScannerWithEmbeddedLibraries(enabled bool) ScannerOption { - return func(s ConfigurableScanner) { - s.SetUseEmbeddedLibraries(enabled) - } } func ScannerWithIncludeDeprecatedChecks(enabled bool) ScannerOption { @@ -64,47 +16,11 @@ func ScannerWithIncludeDeprecatedChecks(enabled bool) ScannerOption { } } -// ScannerWithTrace specifies an io.Writer for trace logs (mainly rego tracing) - if not set, they are discarded -func ScannerWithTrace(w io.Writer) ScannerOption { - return func(s ConfigurableScanner) { - s.SetTraceWriter(w) - } -} - -func ScannerWithPerResultTracing(enabled bool) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPerResultTracingEnabled(enabled) - } -} - -func ScannerWithPolicyDirs(paths ...string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyDirs(paths...) - } -} - -func ScannerWithDataDirs(paths ...string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetDataDirs(paths...) - } -} - -// ScannerWithPolicyNamespaces - namespaces which indicate rego policies containing enforced rules -func ScannerWithPolicyNamespaces(namespaces ...string) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyNamespaces(namespaces...) - } -} - -func ScannerWithPolicyFilesystem(f fs.FS) ScannerOption { - return func(s ConfigurableScanner) { - s.SetPolicyFilesystem(f) - } -} +type ScannerOption func(s ConfigurableScanner) -func ScannerWithDataFilesystem(f fs.FS) ScannerOption { +func ScannerWithFrameworks(frameworks ...framework.Framework) ScannerOption { return func(s ConfigurableScanner) { - s.SetDataFilesystem(f) + s.SetFrameworks(frameworks) } } @@ -113,15 +29,3 @@ func ScannerWithRegoOnly(regoOnly bool) ScannerOption { s.SetRegoOnly(regoOnly) } } - -func ScannerWithRegoErrorLimits(limit int) ScannerOption { - return func(s ConfigurableScanner) { - s.SetRegoErrorLimit(limit) - } -} - -func ScannerWithCustomSchemas(schemas map[string][]byte) ScannerOption { - return func(s ConfigurableScanner) { - s.SetCustomSchemas(schemas) - } -} diff --git a/pkg/iac/scanners/terraform/fs_test.go b/pkg/iac/scanners/terraform/fs_test.go index 649062792514..fb5448873607 100644 --- a/pkg/iac/scanners/terraform/fs_test.go +++ b/pkg/iac/scanners/terraform/fs_test.go @@ -8,13 +8,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" + "github.com/aquasecurity/trivy/pkg/iac/rego" ) func Test_OS_FS(t *testing.T) { s := New( - options.ScannerWithEmbeddedPolicies(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(true), + rego.WithEmbeddedLibraries(true), ) results, err := s.ScanFS(context.TODO(), os.DirFS("testdata"), "fail") require.NoError(t, err) diff --git a/pkg/iac/scanners/terraform/ignore_test.go b/pkg/iac/scanners/terraform/ignore_test.go index 4a2cbce14a86..a42abc323d31 100644 --- a/pkg/iac/scanners/terraform/ignore_test.go +++ b/pkg/iac/scanners/terraform/ignore_test.go @@ -11,6 +11,7 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/providers" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rules" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" @@ -956,11 +957,11 @@ deny[res] { }` localScanner := New( - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyReader(strings.NewReader(check)), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyReader(strings.NewReader(check)), ScannerWithDownloadsAllowed(false), ScannerWithSkipCachedModules(true), ) diff --git a/pkg/iac/scanners/terraform/scanner.go b/pkg/iac/scanners/terraform/scanner.go index d01afb8d962e..d574acdb2c4a 100644 --- a/pkg/iac/scanners/terraform/scanner.go +++ b/pkg/iac/scanners/terraform/scanner.go @@ -3,7 +3,6 @@ package terraform import ( "context" "fmt" - "io" "io/fs" "path" "path/filepath" @@ -28,48 +27,27 @@ var _ options.ConfigurableScanner = (*Scanner)(nil) var _ ConfigurableTerraformScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - parserOpt []parser.Option - executorOpt []executor.Option - dirs map[string]struct{} - forceAllDirs bool - policyDirs []string - policyReaders []io.Reader - regoScanner *rego.Scanner - execLock sync.RWMutex - - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + parserOpt []parser.Option + executorOpt []executor.Option + dirs map[string]struct{} + forceAllDirs bool + regoScanner *rego.Scanner + execLock sync.RWMutex } func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { s.executorOpt = append(s.executorOpt, executor.OptionWithIncludeDeprecatedChecks(b)) } -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - func (s *Scanner) SetRegoOnly(regoOnly bool) { s.executorOpt = append(s.executorOpt, executor.OptionWithRegoOnly(regoOnly)) } func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b + s.executorOpt = append(s.executorOpt, executor.OptionWithFrameworks(frameworks...)) } func (s *Scanner) Name() string { @@ -88,32 +66,6 @@ func (s *Scanner) AddExecutorOptions(opts ...executor.Option) { s.executorOpt = append(s.executorOpt, opts...) } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func New(opts ...options.ScannerOption) *Scanner { s := &Scanner{ dirs: make(map[string]struct{}), @@ -133,7 +85,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceCloud, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner @@ -166,7 +118,7 @@ func (s *Scanner) ScanFS(ctx context.Context, target fs.FS, dir string) (scan.Re } s.execLock.Lock() - s.executorOpt = append(s.executorOpt, executor.OptionWithRegoScanner(regoScanner), executor.OptionWithFrameworks(s.frameworks...)) + s.executorOpt = append(s.executorOpt, executor.OptionWithRegoScanner(regoScanner)) s.execLock.Unlock() var allResults scan.Results diff --git a/pkg/iac/scanners/terraform/scanner_integration_test.go b/pkg/iac/scanners/terraform/scanner_integration_test.go index 098d6a91d450..96c681e97553 100644 --- a/pkg/iac/scanners/terraform/scanner_integration_test.go +++ b/pkg/iac/scanners/terraform/scanner_integration_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) @@ -44,10 +45,10 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), options.ScannerWithRegoOnly(true), ScannerWithAllDirectories(true), ScannerWithSkipCachedModules(true), @@ -101,10 +102,10 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), options.ScannerWithRegoOnly(true), ScannerWithAllDirectories(true), ScannerWithSkipCachedModules(true), @@ -147,10 +148,10 @@ deny[cause] { t.Run("without skip", func(t *testing.T) { scanner := New( ScannerWithSkipCachedModules(true), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "test") require.NoError(t, err) @@ -163,10 +164,10 @@ deny[cause] { scanner := New( ScannerWithSkipDownloaded(true), ScannerWithSkipCachedModules(true), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "test") require.NoError(t, err) @@ -217,10 +218,10 @@ deny[res] { scanner := New( ScannerWithSkipDownloaded(true), ScannerWithSkipCachedModules(true), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(false), ) results, err := scanner.ScanFS(context.TODO(), fs, "test") require.NoError(t, err) diff --git a/pkg/iac/scanners/terraform/scanner_test.go b/pkg/iac/scanners/terraform/scanner_test.go index cd1663ec0eda..39ee35e81321 100644 --- a/pkg/iac/scanners/terraform/scanner_test.go +++ b/pkg/iac/scanners/terraform/scanner_test.go @@ -11,6 +11,7 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/providers" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/rules" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" @@ -76,8 +77,8 @@ deny[cause] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), ) @@ -213,8 +214,8 @@ cause := bucket.name }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyNamespaces(test.includedNamespaces...), + rego.WithPolicyDirs("rules"), + rego.WithPolicyNamespaces(test.includedNamespaces...), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -270,7 +271,7 @@ deny[cause] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), ) @@ -318,9 +319,9 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -386,9 +387,9 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -470,9 +471,9 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedLibraries(true), ) results, err := scanner.ScanFS(context.TODO(), fs, "code") @@ -643,8 +644,8 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), ) @@ -718,11 +719,11 @@ bucket_name = "test" }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ScannerWithTFVarsPaths("main.tfvars"), ScannerWithConfigsFileSystem(configsFS), @@ -752,11 +753,11 @@ bucket_name = "test" }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ScannerWithTFVarsPaths("main.tfvars"), ScannerWithConfigsFileSystem(fs), @@ -845,10 +846,10 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyFilesystem(fs), - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(false), + rego.WithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), options.ScannerWithRegoOnly(true), ScannerWithAllDirectories(true), ) @@ -915,11 +916,11 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ) @@ -984,11 +985,11 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ) @@ -1048,13 +1049,13 @@ deny[res] { }) scanner := New( - options.ScannerWithPolicyDirs("rules"), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs("rules"), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithRegoErrorLimits(0), + rego.WithPolicyNamespaces("user"), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), + rego.WithRegoErrorLimits(0), ScannerWithAllDirectories(true), ) @@ -1089,9 +1090,9 @@ func TestSkipDeprecatedGoChecks(t *testing.T) { }) scanner := New( - options.ScannerWithPolicyFilesystem(fsys), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), + rego.WithPolicyFilesystem(fsys), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), ScannerWithAllDirectories(true), ) diff --git a/pkg/iac/scanners/terraform/setup_test.go b/pkg/iac/scanners/terraform/setup_test.go index d7a8f0277a96..5b98c438f9c1 100644 --- a/pkg/iac/scanners/terraform/setup_test.go +++ b/pkg/iac/scanners/terraform/setup_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser" @@ -39,7 +40,7 @@ func scanHCL(t *testing.T, source string, opts ...options.ScannerOption) scan.Re "main.tf": source, }) - localScanner := New(append(opts, options.ScannerWithEmbeddedPolicies(false))...) + localScanner := New(append(opts, rego.WithEmbeddedPolicies(false))...) results, err := localScanner.ScanFS(context.TODO(), fs, ".") require.NoError(t, err) return results @@ -51,7 +52,7 @@ func scanJSON(t *testing.T, source string) scan.Results { "main.tf.json": source, }) - s := New(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) + s := New(rego.WithEmbeddedPolicies(true), rego.WithEmbeddedLibraries(true)) results, err := s.ScanFS(context.TODO(), fs, ".") require.NoError(t, err) return results diff --git a/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go b/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go index c7ad3a3b4e0b..992bed5af809 100644 --- a/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/snapshot/scanner_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" tfscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" @@ -19,12 +20,12 @@ import ( func initScanner(opts ...options.ScannerOption) *Scanner { defaultOpts := []options.ScannerOption{ - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithEmbeddedLibraries(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithPolicyDirs("."), + rego.WithEmbeddedPolicies(false), + rego.WithEmbeddedLibraries(true), + rego.WithPolicyNamespaces("user"), + rego.WithPolicyDirs("."), options.ScannerWithRegoOnly(true), - options.ScannerWithRegoErrorLimits(0), + rego.WithRegoErrorLimits(0), tfscanner.ScannerWithSkipCachedModules(true), } @@ -59,7 +60,7 @@ func TestScanner_Scan(t *testing.T) { policyFS := os.DirFS(filepath.Join("testdata", tt.dir, "checks")) - s := initScanner(options.ScannerWithPolicyFilesystem(policyFS)) + s := initScanner(rego.WithPolicyFilesystem(policyFS)) result, err := s.Scan(context.TODO(), f) require.NoError(t, err) @@ -108,13 +109,13 @@ func Test_ScanFS(t *testing.T) { fs := os.DirFS("testdata") scanner := New( - options.ScannerWithPolicyDirs(path.Join(tc.dir, "checks")), - options.ScannerWithPolicyFilesystem(fs), + rego.WithPolicyDirs(path.Join(tc.dir, "checks")), + rego.WithPolicyFilesystem(fs), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), - options.ScannerWithEmbeddedLibraries(false), - options.ScannerWithEmbeddedPolicies(false), - options.ScannerWithRegoErrorLimits(0), + rego.WithPolicyNamespaces("user"), + rego.WithEmbeddedLibraries(false), + rego.WithEmbeddedPolicies(false), + rego.WithRegoErrorLimits(0), tfscanner.ScannerWithSkipCachedModules(true), ) diff --git a/pkg/iac/scanners/terraformplan/tfjson/scanner.go b/pkg/iac/scanners/terraformplan/tfjson/scanner.go index 8b16ecb43116..b3e8725c42ae 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/scanner.go +++ b/pkg/iac/scanners/terraformplan/tfjson/scanner.go @@ -6,82 +6,20 @@ import ( "io" "io/fs" - "github.com/aquasecurity/trivy/pkg/iac/framework" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" - terraformScanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" - "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/executor" + "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson/parser" "github.com/aquasecurity/trivy/pkg/log" ) type Scanner struct { - parser *parser.Parser - logger *log.Logger - options []options.ScannerOption - spec string - executorOpt []executor.Option - frameworks []framework.Framework - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool - enableEmbeddedLibraries bool - policyDirs []string - policyReaders []io.Reader + parser *parser.Parser + logger *log.Logger + options []options.ScannerOption + tfScanner *terraform.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetRegoOnly(regoOnly bool) { - s.executorOpt = append(s.executorOpt, executor.OptionWithRegoOnly(regoOnly)) -} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetEmbeddedLibrariesEnabled(enabled bool) { - s.enableEmbeddedLibraries = enabled -} - -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) { -} - -func (s *Scanner) SetPerResultTracingEnabled(_ bool) { -} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func (s *Scanner) Name() string { return "Terraform Plan JSON" } @@ -117,12 +55,10 @@ func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Resu func New(opts ...options.ScannerOption) *Scanner { scanner := &Scanner{ - options: opts, - logger: log.WithPrefix("tfjson scanner"), - parser: parser.New(), - } - for _, o := range opts { - o(scanner) + options: opts, + logger: log.WithPrefix("tfjson scanner"), + parser: parser.New(), + tfScanner: terraform.New(opts...), } return scanner @@ -151,6 +87,5 @@ func (s *Scanner) Scan(reader io.Reader) (scan.Results, error) { return nil, fmt.Errorf("failed to convert plan to FS: %w", err) } - scanner := terraformScanner.New(s.options...) - return scanner.ScanFS(context.TODO(), planFS, ".") + return s.tfScanner.ScanFS(context.TODO(), planFS, ".") } diff --git a/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go b/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go index 289147f482dd..9173c8046bb1 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/tfjson/scanner_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) @@ -51,7 +52,7 @@ func Test_TerraformScanner(t *testing.T) { inputFile: "test/testdata/plan.json", check: defaultCheck, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), }, }, @@ -60,9 +61,9 @@ func Test_TerraformScanner(t *testing.T) { inputFile: "test/testdata/plan.json", check: defaultCheck, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), }, }, { @@ -90,9 +91,9 @@ deny[cause] { } `, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), }, }, { @@ -100,9 +101,9 @@ deny[cause] { inputFile: "test/testdata/arbitrary_name.json", check: defaultCheck, options: []options.ScannerOption{ - options.ScannerWithPolicyDirs("rules"), + rego.WithPolicyDirs("rules"), options.ScannerWithRegoOnly(true), - options.ScannerWithPolicyNamespaces("user"), + rego.WithPolicyNamespaces("user"), }, }, } @@ -115,7 +116,7 @@ deny[cause] { "/rules/test.rego": tc.check, }) - so := append(tc.options, options.ScannerWithPolicyFilesystem(fs)) + so := append(tc.options, rego.WithPolicyFilesystem(fs)) scanner := New(so...) results, err := scanner.ScanFS(context.TODO(), fs, "code") diff --git a/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go b/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go index dd77c2d89f6e..1c0ac8234862 100644 --- a/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go +++ b/pkg/iac/scanners/terraformplan/tfjson/test/scanner_test.go @@ -8,15 +8,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson" ) func Test_Scanning_Plan(t *testing.T) { scanner := tfjson.New( - options.ScannerWithEmbeddedPolicies(true), - options.ScannerWithEmbeddedLibraries(true), + rego.WithEmbeddedPolicies(true), + rego.WithEmbeddedLibraries(true), ) b, _ := os.ReadFile("testdata/plan.json") testFS := fstest.MapFS{ diff --git a/pkg/iac/scanners/toml/scanner.go b/pkg/iac/scanners/toml/scanner.go index 235cc65dada5..216d0b1f9697 100644 --- a/pkg/iac/scanners/toml/scanner.go +++ b/pkg/iac/scanners/toml/scanner.go @@ -2,7 +2,6 @@ package toml import ( "context" - "io" "io/fs" "sync" @@ -18,67 +17,21 @@ import ( var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - logger *log.Logger - options []options.ScannerOption - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - frameworks []framework.Framework - spec string - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool + mu sync.Mutex + logger *log.Logger + options []options.ScannerOption + parser *parser.Parser + regoScanner *rego.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetRegoOnly(bool) {} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func (s *Scanner) Name() string { return "TOML" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(_ bool) {} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} - -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ options: opts, @@ -137,7 +90,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceTOML, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/toml/scanner_test.go b/pkg/iac/scanners/toml/scanner_test.go index d3c4e51e3b63..ea5819448288 100644 --- a/pkg/iac/scanners/toml/scanner_test.go +++ b/pkg/iac/scanners/toml/scanner_test.go @@ -9,8 +9,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan(t *testing.T) { @@ -52,7 +52,7 @@ deny[res] { `, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) diff --git a/pkg/iac/scanners/yaml/scanner.go b/pkg/iac/scanners/yaml/scanner.go index 67b661ee5971..565d10df1f83 100644 --- a/pkg/iac/scanners/yaml/scanner.go +++ b/pkg/iac/scanners/yaml/scanner.go @@ -2,7 +2,6 @@ package yaml import ( "context" - "io" "io/fs" "sync" @@ -18,66 +17,21 @@ import ( var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - options []options.ScannerOption - logger *log.Logger - policyDirs []string - policyReaders []io.Reader - parser *parser.Parser - regoScanner *rego.Scanner - frameworks []framework.Framework - spec string - loadEmbeddedLibraries bool - loadEmbeddedPolicies bool + mu sync.Mutex + options []options.ScannerOption + logger *log.Logger + parser *parser.Parser + regoScanner *rego.Scanner } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} -func (s *Scanner) SetCustomSchemas(map[string][]byte) {} - -func (s *Scanner) SetRegoOnly(bool) {} - -func (s *Scanner) SetFrameworks(frameworks []framework.Framework) { - s.frameworks = frameworks -} - -func (s *Scanner) SetSpec(spec string) { - s.spec = spec -} - -func (s *Scanner) SetUseEmbeddedPolicies(b bool) { - s.loadEmbeddedPolicies = b -} - -func (s *Scanner) SetUseEmbeddedLibraries(b bool) { - s.loadEmbeddedLibraries = b -} +func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} +func (s *Scanner) SetRegoOnly(bool) {} +func (s *Scanner) SetFrameworks(frameworks []framework.Framework) {} func (s *Scanner) Name() string { return "YAML" } -func (s *Scanner) SetPolicyReaders(readers []io.Reader) { - s.policyReaders = readers -} - -func (s *Scanner) SetTraceWriter(_ io.Writer) {} -func (s *Scanner) SetPerResultTracingEnabled(_ bool) {} - -func (s *Scanner) SetPolicyDirs(dirs ...string) { - s.policyDirs = dirs -} - -func (s *Scanner) SetDataDirs(_ ...string) {} -func (s *Scanner) SetPolicyNamespaces(_ ...string) {} - -func (s *Scanner) SetPolicyFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetDataFilesystem(_ fs.FS) { - // handled by rego when option is passed on -} -func (s *Scanner) SetRegoErrorLimit(_ int) {} - func NewScanner(opts ...options.ScannerOption) *Scanner { s := &Scanner{ options: opts, @@ -138,7 +92,7 @@ func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) { return s.regoScanner, nil } regoScanner := rego.NewScanner(types.SourceYAML, s.options...) - if err := regoScanner.LoadPolicies(s.loadEmbeddedLibraries, s.loadEmbeddedPolicies, srcFS, s.policyDirs, s.policyReaders); err != nil { + if err := regoScanner.LoadPolicies(srcFS); err != nil { return nil, err } s.regoScanner = regoScanner diff --git a/pkg/iac/scanners/yaml/scanner_test.go b/pkg/iac/scanners/yaml/scanner_test.go index 02468158fcf9..b7c4ec623887 100644 --- a/pkg/iac/scanners/yaml/scanner_test.go +++ b/pkg/iac/scanners/yaml/scanner_test.go @@ -9,8 +9,8 @@ import ( "github.com/aquasecurity/trivy/internal/testutil" "github.com/aquasecurity/trivy/pkg/iac/framework" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" - "github.com/aquasecurity/trivy/pkg/iac/scanners/options" ) func Test_BasicScan(t *testing.T) { @@ -55,7 +55,7 @@ deny[res] { `, }) - scanner := NewScanner(options.ScannerWithPolicyDirs("rules")) + scanner := NewScanner(rego.WithPolicyDirs("rules")) results, err := scanner.ScanFS(context.TODO(), fs, "code") require.NoError(t, err) diff --git a/pkg/misconf/scanner.go b/pkg/misconf/scanner.go index 2e979caba5e9..db203364a3e4 100644 --- a/pkg/misconf/scanner.go +++ b/pkg/misconf/scanner.go @@ -17,6 +17,7 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" "github.com/aquasecurity/trivy/pkg/iac/detection" + "github.com/aquasecurity/trivy/pkg/iac/rego" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners" "github.com/aquasecurity/trivy/pkg/iac/scanners/azure/arm" @@ -208,8 +209,8 @@ func (s *Scanner) filterFS(fsys fs.FS) (fs.FS, error) { func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerOption, error) { opts := []options.ScannerOption{ - options.ScannerWithEmbeddedPolicies(!opt.DisableEmbeddedPolicies), - options.ScannerWithEmbeddedLibraries(!opt.DisableEmbeddedLibraries), + rego.WithEmbeddedPolicies(!opt.DisableEmbeddedPolicies), + rego.WithEmbeddedLibraries(!opt.DisableEmbeddedLibraries), options.ScannerWithIncludeDeprecatedChecks(opt.IncludeDeprecatedChecks), } @@ -218,7 +219,7 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO return nil, err } if policyFS != nil { - opts = append(opts, options.ScannerWithPolicyFilesystem(policyFS)) + opts = append(opts, rego.WithPolicyFilesystem(policyFS)) } dataFS, dataPaths, err := CreateDataFS(opt.DataPaths, opt.K8sVersion) @@ -231,13 +232,13 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO }) opts = append(opts, - options.ScannerWithDataDirs(dataPaths...), - options.ScannerWithDataFilesystem(dataFS), - options.ScannerWithCustomSchemas(schemas), + rego.WithDataDirs(dataPaths...), + rego.WithDataFilesystem(dataFS), + rego.WithCustomSchemas(schemas), ) if opt.Trace { - opts = append(opts, options.ScannerWithPerResultTracing(true)) + opts = append(opts, rego.WithPerResultTracing(true)) } if opt.RegoOnly { @@ -245,15 +246,15 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO } if len(policyPaths) > 0 { - opts = append(opts, options.ScannerWithPolicyDirs(policyPaths...)) + opts = append(opts, rego.WithPolicyDirs(policyPaths...)) } if len(opt.DataPaths) > 0 { - opts = append(opts, options.ScannerWithDataDirs(opt.DataPaths...)) + opts = append(opts, rego.WithDataDirs(opt.DataPaths...)) } if len(opt.Namespaces) > 0 { - opts = append(opts, options.ScannerWithPolicyNamespaces(opt.Namespaces...)) + opts = append(opts, rego.WithPolicyNamespaces(opt.Namespaces...)) } switch t {