From f7fb6a4bca13b7e4e8f70b2ee6315b976f82e9ce Mon Sep 17 00:00:00 2001 From: Wen Zhou Date: Fri, 29 Jul 2022 14:09:08 +0200 Subject: [PATCH] feat(misconf): add --file-patterns for terraform misconfiguration - docs: make usage --file-patterns clear as it still includes default files - test: add case for dockerfile as name 'Containerfile' - test: add case for terraform .tf.json --- docs/docs/references/cli/client.md | 2 +- docs/docs/references/cli/config.md | 3 +- docs/docs/references/cli/fs.md | 4 +- docs/docs/references/cli/image.md | 2 +- docs/docs/references/cli/repo.md | 4 +- docs/docs/references/cli/rootfs.md | 4 +- pkg/commands/app.go | 1 + pkg/fanal/analyzer/config/config.go | 6 +- .../analyzer/config/dockerfile/docker_test.go | 5 ++ pkg/fanal/analyzer/config/helm/helm.go | 2 +- .../analyzer/config/terraform/terraform.go | 8 ++- .../config/terraform/terraform_test.go | 56 ++++++++++++++++--- pkg/flag/misconf_flags.go | 2 +- 13 files changed, 75 insertions(+), 24 deletions(-) diff --git a/docs/docs/references/cli/client.md b/docs/docs/references/cli/client.md index 3113c346c699..2b6d91f70af1 100644 --- a/docs/docs/references/cli/client.md +++ b/docs/docs/references/cli/client.md @@ -47,7 +47,7 @@ Vulnerability Flags Misconfiguration Flags --config-data strings specify paths from which data for the Rego policies will be recursively loaded --config-policy strings specify paths to the Rego policy files directory, applying config files - --file-patterns strings specify config file patterns, available with '--security-checks config' + --file-patterns strings specify additional config file mathcing in regex format, available with '--security-checks config' --include-non-failures include successes and exceptions, available with '--security-checks config' --policy-namespaces strings Rego namespaces --trace enable more verbose trace output for custom queries diff --git a/docs/docs/references/cli/config.md b/docs/docs/references/cli/config.md index ee753037bbe5..05873886f5c4 100644 --- a/docs/docs/references/cli/config.md +++ b/docs/docs/references/cli/config.md @@ -2,6 +2,7 @@ ``` bash Scan config files for misconfigurations +Support: Dockerfile/Containerfile, Yaml, JSON, Helm, Terraform, CloudFormation Usage: trivy config [flags] DIR @@ -32,7 +33,7 @@ Cache Flags Misconfiguration Flags --config-data strings specify paths from which data for the Rego policies will be recursively loaded --config-policy strings specify paths to the Rego policy files directory, applying config files - --file-patterns strings specify config file patterns, available with '--security-checks config' + --file-patterns strings specify additional config file mathcing in regex format, available with '--security-checks config' --include-non-failures include successes and exceptions, available with '--security-checks config' --policy-namespaces strings Rego namespaces --trace enable more verbose trace output for custom queries diff --git a/docs/docs/references/cli/fs.md b/docs/docs/references/cli/fs.md index a7bf002ea811..715572d5a98a 100644 --- a/docs/docs/references/cli/fs.md +++ b/docs/docs/references/cli/fs.md @@ -55,7 +55,7 @@ Vulnerability Flags Misconfiguration Flags --config-data strings specify paths from which data for the Rego policies will be recursively loaded --config-policy strings specify paths to the Rego policy files directory, applying config files - --file-patterns strings specify config file patterns, available with '--security-checks config' + --file-patterns strings specify additional config file mathcing in regex format, available with '--security-checks config' --include-non-failures include successes and exceptions, available with '--security-checks config' --policy-namespaces strings Rego namespaces --trace enable more verbose trace output for custom queries @@ -82,4 +82,4 @@ Global Flags: -q, --quiet suppress progress bar and log output --timeout duration timeout (default 5m0s) -v, --version show version -``` \ No newline at end of file +``` diff --git a/docs/docs/references/cli/image.md b/docs/docs/references/cli/image.md index 2d345eaf7481..69840cf6ee42 100644 --- a/docs/docs/references/cli/image.md +++ b/docs/docs/references/cli/image.md @@ -73,7 +73,7 @@ Vulnerability Flags Misconfiguration Flags --config-data strings specify paths from which data for the Rego policies will be recursively loaded --config-policy strings specify paths to the Rego policy files directory, applying config files - --file-patterns strings specify config file patterns, available with '--security-checks config' + --file-patterns strings specify additional config file mathcing in regex format, available with '--security-checks config' --include-non-failures include successes and exceptions, available with '--security-checks config' --policy-namespaces strings Rego namespaces --trace enable more verbose trace output for custom queries diff --git a/docs/docs/references/cli/repo.md b/docs/docs/references/cli/repo.md index a3dc29e9ceb2..16ddcf8aab53 100644 --- a/docs/docs/references/cli/repo.md +++ b/docs/docs/references/cli/repo.md @@ -52,7 +52,7 @@ Vulnerability Flags Misconfiguration Flags --config-data strings specify paths from which data for the Rego policies will be recursively loaded --config-policy strings specify paths to the Rego policy files directory, applying config files - --file-patterns strings specify config file patterns, available with '--security-checks config' + --file-patterns strings specify additional config file mathcing in regex format, available with '--security-checks config' --include-non-failures include successes and exceptions, available with '--security-checks config' --policy-namespaces strings Rego namespaces --trace enable more verbose trace output for custom queries @@ -84,4 +84,4 @@ Global Flags: -q, --quiet suppress progress bar and log output --timeout duration timeout (default 5m0s) -v, --version show version -``` \ No newline at end of file +``` diff --git a/docs/docs/references/cli/rootfs.md b/docs/docs/references/cli/rootfs.md index bdba1ffb38b3..8637dca08691 100644 --- a/docs/docs/references/cli/rootfs.md +++ b/docs/docs/references/cli/rootfs.md @@ -55,7 +55,7 @@ Vulnerability Flags Misconfiguration Flags --config-data strings specify paths from which data for the Rego policies will be recursively loaded --config-policy strings specify paths to the Rego policy files directory, applying config files - --file-patterns strings specify config file patterns, available with '--security-checks config' + --file-patterns strings specify additional config file mathcing in regex format, available with '--security-checks config' --include-non-failures include successes and exceptions, available with '--security-checks config' --policy-namespaces strings Rego namespaces --trace enable more verbose trace output for custom queries @@ -76,4 +76,4 @@ Global Flags: -q, --quiet suppress progress bar and log output --timeout duration timeout (default 5m0s) -v, --version show version -``` \ No newline at end of file +``` diff --git a/pkg/commands/app.go b/pkg/commands/app.go index b93e26284f88..87c40c7ab18e 100644 --- a/pkg/commands/app.go +++ b/pkg/commands/app.go @@ -542,6 +542,7 @@ func NewConfigCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command { Use: "config [flags] DIR", Aliases: []string{"conf"}, Short: "Scan config files for misconfigurations", + Long: "Support: Dockerfile/Containerfile, Yaml, JSON, Helm, Terraform, CloudFormation", PreRunE: func(cmd *cobra.Command, args []string) error { if err := configFlags.Bind(cmd); err != nil { return xerrors.Errorf("flag bind error: %w", err) diff --git a/pkg/fanal/analyzer/config/config.go b/pkg/fanal/analyzer/config/config.go index c8d4b833b767..3ec665924c2c 100644 --- a/pkg/fanal/analyzer/config/config.go +++ b/pkg/fanal/analyzer/config/config.go @@ -37,7 +37,7 @@ func (o *ScannerOption) Sort() { } func RegisterConfigAnalyzers(filePatterns []string) error { - var dockerRegexp, jsonRegexp, yamlRegexp, helmRegexp *regexp.Regexp + var dockerRegexp, jsonRegexp, yamlRegexp, helmRegexp, terraformRegexp *regexp.Regexp for _, p := range filePatterns { // e.g. "dockerfile:my_dockerfile_*" s := strings.SplitN(p, separator, 2) @@ -59,13 +59,15 @@ func RegisterConfigAnalyzers(filePatterns []string) error { yamlRegexp = r case types.Helm: helmRegexp = r + case types.Terraform: + terraformRegexp = r default: return xerrors.Errorf("unknown file type: %s, pattern: %s", fileType, pattern) } } analyzer.RegisterAnalyzer(dockerfile.NewConfigAnalyzer(dockerRegexp)) - analyzer.RegisterAnalyzer(terraform.NewConfigAnalyzer()) + analyzer.RegisterAnalyzer(terraform.NewConfigAnalyzer(terraformRegexp)) analyzer.RegisterAnalyzer(json.NewConfigAnalyzer(jsonRegexp)) analyzer.RegisterAnalyzer(yaml.NewConfigAnalyzer(yamlRegexp)) analyzer.RegisterAnalyzer(helm.NewConfigAnalyzer(helmRegexp)) diff --git a/pkg/fanal/analyzer/config/dockerfile/docker_test.go b/pkg/fanal/analyzer/config/dockerfile/docker_test.go index dbcc9a6842b1..5204482fe21c 100644 --- a/pkg/fanal/analyzer/config/dockerfile/docker_test.go +++ b/pkg/fanal/analyzer/config/dockerfile/docker_test.go @@ -118,6 +118,11 @@ func Test_dockerConfigAnalyzer_Required(t *testing.T) { filePath: "docker/Dockerfile", want: true, }, + { + name: "Containerfile in dir", + filePath: "Containerfile", + want: true, + }, { name: "Dockerfile as prefix", filePath: "Dockerfilebuild", diff --git a/pkg/fanal/analyzer/config/helm/helm.go b/pkg/fanal/analyzer/config/helm/helm.go index 129c4c36fb9a..cd4f5896a79a 100644 --- a/pkg/fanal/analyzer/config/helm/helm.go +++ b/pkg/fanal/analyzer/config/helm/helm.go @@ -79,7 +79,7 @@ func (a ConfigAnalyzer) Required(filePath string, info os.FileInfo) bool { } name := filepath.Base(filePath) - for _, acceptable := range []string{"Chart.yaml", ".helmignore"} { + for _, acceptable := range []string{".helmignore"} { if strings.EqualFold(name, acceptable) { return true } diff --git a/pkg/fanal/analyzer/config/terraform/terraform.go b/pkg/fanal/analyzer/config/terraform/terraform.go index 99d2a3b121e6..20e98c6c85aa 100644 --- a/pkg/fanal/analyzer/config/terraform/terraform.go +++ b/pkg/fanal/analyzer/config/terraform/terraform.go @@ -5,6 +5,7 @@ import ( "io" "os" "path/filepath" + "regexp" "golang.org/x/exp/slices" "golang.org/x/xerrors" @@ -18,10 +19,13 @@ const version = 1 var requiredExts = []string{".tf", ".tf.json"} type ConfigAnalyzer struct { + filePattern *regexp.Regexp } -func NewConfigAnalyzer() ConfigAnalyzer { - return ConfigAnalyzer{} +func NewConfigAnalyzer(filePattern *regexp.Regexp) ConfigAnalyzer { + return ConfigAnalyzer{ + filePattern: filePattern, + } } // Analyze returns a name of Terraform file diff --git a/pkg/fanal/analyzer/config/terraform/terraform_test.go b/pkg/fanal/analyzer/config/terraform/terraform_test.go index 225cb25b614f..bebd534e8e2b 100644 --- a/pkg/fanal/analyzer/config/terraform/terraform_test.go +++ b/pkg/fanal/analyzer/config/terraform/terraform_test.go @@ -13,14 +13,14 @@ import ( "github.com/aquasecurity/trivy/pkg/fanal/types" ) -func TestConfigAnalyzer_Analyze(t *testing.T) { +func Test_TerraformConfigAnalyzer_Analyze(t *testing.T) { tests := []struct { name string input analyzer.AnalysisInput want *analyzer.AnalysisResult }{ { - name: "happy path", + name: "happy path1", input: analyzer.AnalysisInput{ Dir: "path/to/", FilePath: "main.tf", @@ -38,10 +38,29 @@ func TestConfigAnalyzer_Analyze(t *testing.T) { }, }, }, + { + name: "happy path2", + input: analyzer.AnalysisInput{ + Dir: "path/to/", + FilePath: "main.tf.json", + Content: bytes.NewReader(nil), + }, + want: &analyzer.AnalysisResult{ + Files: map[types.HandlerType][]types.File{ + types.MisconfPostHandler: { + { + Type: types.Terraform, + Path: "main.tf.json", + Content: []byte{}, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - a := terraform.ConfigAnalyzer{} + a := terraform.NewConfigAnalyzer(tt.filePattern) ctx := context.Background() got, err := a.Analyze(ctx, tt.input) @@ -51,17 +70,23 @@ func TestConfigAnalyzer_Analyze(t *testing.T) { } } -func TestConfigAnalyzer_Required(t *testing.T) { +func Test_TerraformConfigAnalyzer_Required(t *testing.T) { tests := []struct { - name string - filePath string - want bool + name string + filePattern *regexp.Regexp + filePath string + want bool }{ { - name: "happy path", + name: "happy path1", filePath: "/path/to/main.tf", want: true, }, + { + name: "happy path2", + filePath: "/path/to/main.tf.json", + want: true, + }, { name: "hcl", filePath: "/path/to/main.hcl", @@ -72,12 +97,25 @@ func TestConfigAnalyzer_Required(t *testing.T) { filePath: "deployment.yaml", want: false, }, + { + name: "file pattern", + filePattern: regexp.MustCompile(`foo*`), + filePath: "foo_file", + want: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - a := terraform.ConfigAnalyzer{} + a := terraform.NewConfigAnalyzer(tt.filePattern) got := a.Required(tt.filePath, nil) assert.Equal(t, tt.want, got) }) } } + +func Test_TerraformConfigAnalyzer_Type(t *testing.T) { + a := terraform.NewConfigAnalyzer(nil) + want := analyzer.TypeTerraform + got := a.Type() + assert.Equal(t, want, got) +} diff --git a/pkg/flag/misconf_flags.go b/pkg/flag/misconf_flags.go index 897fa2b4715a..2693a1123a46 100644 --- a/pkg/flag/misconf_flags.go +++ b/pkg/flag/misconf_flags.go @@ -14,7 +14,7 @@ var ( Name: "file-patterns", ConfigName: "misconfiguration.file-patterns", Value: []string{}, - Usage: "specify config file patterns, available with '--security-checks config'", + Usage: "specify additional config file mathcing in regex format, available with '--security-checks config'", } IncludeNonFailuresFlag = Flag{ Name: "include-non-failures",