From 2a6c7ab3b338ce4a8f99d6ac3508c2531dcbe812 Mon Sep 17 00:00:00 2001 From: Nikita Pivkin Date: Sat, 24 Aug 2024 02:00:09 +0600 Subject: [PATCH] fix(misconf): support deprecating for Go checks (#7377) Signed-off-by: nikpivkin --- pkg/iac/scanners/azure/arm/scanner.go | 38 ++++++++------ pkg/iac/scanners/cloudformation/scanner.go | 38 ++++++++------ .../scanners/terraform/executor/executor.go | 25 ++++++--- pkg/iac/scanners/terraform/executor/option.go | 6 +++ pkg/iac/scanners/terraform/scanner.go | 5 +- pkg/iac/scanners/terraform/scanner_test.go | 52 +++++++++++++++++++ 6 files changed, 123 insertions(+), 41 deletions(-) diff --git a/pkg/iac/scanners/azure/arm/scanner.go b/pkg/iac/scanners/azure/arm/scanner.go index 66bab2b4f806..e4b3258f823f 100644 --- a/pkg/iac/scanners/azure/arm/scanner.go +++ b/pkg/iac/scanners/azure/arm/scanner.go @@ -25,20 +25,24 @@ var _ scanners.FSScanner = (*Scanner)(nil) var _ options.ConfigurableScanner = (*Scanner)(nil) type Scanner struct { - mu sync.Mutex - scannerOptions []options.ScannerOption - logger *log.Logger - frameworks []framework.Framework - regoOnly bool - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool - policyDirs []string - policyReaders []io.Reader - regoScanner *rego.Scanner - spec string -} - -func (s *Scanner) SetIncludeDeprecatedChecks(b bool) {} + mu sync.Mutex + scannerOptions []options.ScannerOption + logger *log.Logger + frameworks []framework.Framework + regoOnly bool + loadEmbeddedPolicies bool + loadEmbeddedLibraries bool + policyDirs []string + policyReaders []io.Reader + regoScanner *rego.Scanner + spec string + includeDeprecatedChecks bool +} + +func (s *Scanner) SetIncludeDeprecatedChecks(b bool) { + s.includeDeprecatedChecks = b +} + func (s *Scanner) SetCustomSchemas(map[string][]byte) {} func (s *Scanner) SetSpec(spec string) { @@ -150,9 +154,11 @@ func (s *Scanner) scanDeployment(ctx context.Context, deployment azure.Deploymen return nil, ctx.Err() default: } - if rule.GetRule().RegoPackage != "" { - continue + + if !s.includeDeprecatedChecks && rule.Deprecated { + continue // skip deprecated checks } + ruleResults := rule.Evaluate(deploymentState) if len(ruleResults) > 0 { results = append(results, ruleResults...) diff --git a/pkg/iac/scanners/cloudformation/scanner.go b/pkg/iac/scanners/cloudformation/scanner.go index 6db08c0d15bb..e7677926944d 100644 --- a/pkg/iac/scanners/cloudformation/scanner.go +++ b/pkg/iac/scanners/cloudformation/scanner.go @@ -48,22 +48,26 @@ 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 - regoOnly bool - loadEmbeddedPolicies bool - loadEmbeddedLibraries bool - options []options.ScannerOption - parserOptions []parser.Option - frameworks []framework.Framework - spec string + 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 +} + +func (s *Scanner) SetIncludeDeprecatedChecks(bool) { + s.includeDeprecatedChecks = true } -func (s *Scanner) SetIncludeDeprecatedChecks(bool) {} func (s *Scanner) SetCustomSchemas(map[string][]byte) {} func (s *Scanner) addParserOption(opt parser.Option) { @@ -211,9 +215,11 @@ func (s *Scanner) scanFileContext(ctx context.Context, regoScanner *rego.Scanner return nil, ctx.Err() default: } - if rule.GetRule().RegoPackage != "" { - continue + + if !s.includeDeprecatedChecks && rule.Deprecated { + continue // skip deprecated checks } + evalResult := rule.Evaluate(state) if len(evalResult) > 0 { for _, scanResult := range evalResult { diff --git a/pkg/iac/scanners/terraform/executor/executor.go b/pkg/iac/scanners/terraform/executor/executor.go index c6337a2bfd1d..e7561997305d 100644 --- a/pkg/iac/scanners/terraform/executor/executor.go +++ b/pkg/iac/scanners/terraform/executor/executor.go @@ -5,6 +5,7 @@ import ( "runtime" "sort" + "github.com/samber/lo" "github.com/zclconf/go-cty/cty" adapter "github.com/aquasecurity/trivy/pkg/iac/adapters/terraform" @@ -15,17 +16,19 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/terraform" "github.com/aquasecurity/trivy/pkg/iac/types" + ruleTypes "github.com/aquasecurity/trivy/pkg/iac/types/rules" "github.com/aquasecurity/trivy/pkg/log" ) // Executor scans HCL blocks by running all registered rules against them type Executor struct { - workspaceName string - logger *log.Logger - resultsFilters []func(scan.Results) scan.Results - regoScanner *rego.Scanner - regoOnly bool - frameworks []framework.Framework + workspaceName string + logger *log.Logger + resultsFilters []func(scan.Results) scan.Results + regoScanner *rego.Scanner + regoOnly bool + includeDeprecatedChecks bool + frameworks []framework.Framework } // New creates a new Executor @@ -53,8 +56,14 @@ func (e *Executor) Execute(modules terraform.Modules) (scan.Results, error) { e.logger.Debug("Using max routines", log.Int("count", threads)) - registeredRules := rules.GetRegistered(e.frameworks...) - e.logger.Debug("Initialized rule(s).", log.Int("count", len(registeredRules))) + registeredRules := lo.Filter(rules.GetRegistered(e.frameworks...), func(r ruleTypes.RegisteredRule, _ int) bool { + if !e.includeDeprecatedChecks && r.Deprecated { + return false // skip deprecated checks + } + + return true + }) + e.logger.Debug("Initialized Go check(s).", log.Int("count", len(registeredRules))) pool := NewPool(threads, registeredRules, modules, infra, e.regoScanner, e.regoOnly) diff --git a/pkg/iac/scanners/terraform/executor/option.go b/pkg/iac/scanners/terraform/executor/option.go index d2414878c98f..70dd1a9520c3 100644 --- a/pkg/iac/scanners/terraform/executor/option.go +++ b/pkg/iac/scanners/terraform/executor/option.go @@ -37,3 +37,9 @@ func OptionWithRegoOnly(regoOnly bool) Option { e.regoOnly = regoOnly } } + +func OptionWithIncludeDeprecatedChecks(b bool) Option { + return func(e *Executor) { + e.includeDeprecatedChecks = b + } +} diff --git a/pkg/iac/scanners/terraform/scanner.go b/pkg/iac/scanners/terraform/scanner.go index 080d26c0d155..d01afb8d962e 100644 --- a/pkg/iac/scanners/terraform/scanner.go +++ b/pkg/iac/scanners/terraform/scanner.go @@ -46,7 +46,10 @@ type Scanner struct { loadEmbeddedPolicies bool } -func (s *Scanner) SetIncludeDeprecatedChecks(b bool) {} +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) { diff --git a/pkg/iac/scanners/terraform/scanner_test.go b/pkg/iac/scanners/terraform/scanner_test.go index 5c85995027f4..cd1663ec0eda 100644 --- a/pkg/iac/scanners/terraform/scanner_test.go +++ b/pkg/iac/scanners/terraform/scanner_test.go @@ -10,8 +10,13 @@ import ( "github.com/stretchr/testify/require" "github.com/aquasecurity/trivy/internal/testutil" + "github.com/aquasecurity/trivy/pkg/iac/providers" + "github.com/aquasecurity/trivy/pkg/iac/rules" "github.com/aquasecurity/trivy/pkg/iac/scan" "github.com/aquasecurity/trivy/pkg/iac/scanners/options" + "github.com/aquasecurity/trivy/pkg/iac/severity" + "github.com/aquasecurity/trivy/pkg/iac/state" + "github.com/aquasecurity/trivy/pkg/iac/types" ) const emptyBucketRule = ` @@ -1065,3 +1070,50 @@ deny[res] { occurrences := failed[0].Occurrences() assert.Equal(t, "code/example/main.tf", occurrences[0].Filename) } + +func TestSkipDeprecatedGoChecks(t *testing.T) { + + check := scan.Rule{ + Provider: providers.AWSProvider, + Service: "service", + ShortCode: "abc", + Severity: severity.High, + Check: func(s *state.State) (results scan.Results) { + results.Add("Deny", types.NewTestMetadata()) + return + }, + } + + fsys := testutil.CreateFS(t, map[string]string{ + "main.tf": `resource "foo" "bar" {}`, + }) + + scanner := New( + options.ScannerWithPolicyFilesystem(fsys), + options.ScannerWithEmbeddedLibraries(false), + options.ScannerWithEmbeddedPolicies(false), + ScannerWithAllDirectories(true), + ) + + t.Run("deprecated", func(t *testing.T) { + check.Deprecated = true + reg := rules.Register(check) + defer rules.Deregister(reg) + + results, err := scanner.ScanFS(context.TODO(), fsys, ".") + require.NoError(t, err) + + require.Empty(t, results) + }) + + t.Run("not deprecated", func(t *testing.T) { + check.Deprecated = false + reg := rules.Register(check) + defer rules.Deregister(reg) + + results, err := scanner.ScanFS(context.TODO(), fsys, ".") + require.NoError(t, err) + + require.Len(t, results, 1) + }) +}