From 6358b97f27a3377c0c403bd48968895fb2054a10 Mon Sep 17 00:00:00 2001 From: Nasir Rabbani Date: Wed, 2 Feb 2022 18:32:34 +0530 Subject: [PATCH 1/6] added flag to get config with errors --- pkg/cli/run.go | 11 +- pkg/cli/run_test.go | 355 +++++++++--------- pkg/cli/scan.go | 1 + pkg/http-server/file-scan.go | 16 +- pkg/http-server/remote-repo.go | 5 +- .../admission-webhook/validating-webhook.go | 2 +- pkg/runtime/executor.go | 12 +- pkg/runtime/executor_test.go | 2 +- test/e2e/help/golden/help_scan.txt | 1 + 9 files changed, 225 insertions(+), 180 deletions(-) diff --git a/pkg/cli/run.go b/pkg/cli/run.go index 0f6932f0a..4c5d2287b 100644 --- a/pkg/cli/run.go +++ b/pkg/cli/run.go @@ -66,6 +66,9 @@ type ScanOptions struct { // configOnly will output resource config (should only be used for debugging purposes) configOnly bool + // configWithError will output resource config and encountered errors + configWithError bool + // config file path configFile string @@ -207,7 +210,7 @@ func (s *ScanOptions) Run() error { } // executor output - results, err := executor.Execute(s.configOnly) + results, err := executor.Execute(s.configOnly, s.configWithError) if err != nil { return err } @@ -224,7 +227,7 @@ func (s *ScanOptions) Run() error { return err } - if !s.configOnly && flag.Lookup("test.v") == nil { + if !s.configOnly && flag.Lookup("test.v") == nil && !s.configWithError { os.RemoveAll(tempDir) exitCode := getExitCode(results) if exitCode != 0 { @@ -258,6 +261,10 @@ func (s ScanOptions) writeResults(results runtime.Output) error { return writer.Write(s.outputType, results.ResourceConfig, outputWriter) } + if s.configWithError { + return writer.Write(s.outputType, results, outputWriter) + } + // add verbose flag to the scan summary results.Violations.ViolationStore.Summary.ShowViolationDetails = s.verbose diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go index a96e3de0c..9599c031b 100644 --- a/pkg/cli/run_test.go +++ b/pkg/cli/run_test.go @@ -62,12 +62,12 @@ func TestRun(t *testing.T) { log.SetOutput(ioutil.Discard) } - kustomizeTestDirPath := filepath.Join(runTestDir, "kustomize-test") + // kustomizeTestDirPath := filepath.Join(runTestDir, "kustomize-test") testTerraformFilePath := filepath.Join(runTestDir, "config-only.tf") - testRemoteModuleFilePath := filepath.Join(runTestDir, "remote-modules.tf") - testTFJSONFilePath := filepath.Join(runTestDir, "tf-plan.json") + // testRemoteModuleFilePath := filepath.Join(runTestDir, "remote-modules.tf") + // testTFJSONFilePath := filepath.Join(runTestDir, "tf-plan.json") - ruleSlice := []string{"AWS.ECR.DataSecurity.High.0579", "AWS.SecurityGroup.NetworkPortsSecurity.Low.0561"} + // ruleSlice := []string{"AWS.ECR.DataSecurity.High.0579", "AWS.SecurityGroup.NetworkPortsSecurity.Low.0561"} table := []struct { name string @@ -77,177 +77,186 @@ func TestRun(t *testing.T) { want string wantErr bool }{ - { - name: "normal terraform run", - scanOptions: &ScanOptions{ - // policy type terraform is not supported, error expected - policyType: []string{"terraform"}, - iacDirPath: runTestDir, - }, - wantErr: true, - }, - { - name: "normal terraform run with successful output", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacDirPath: runTestDir, - outputType: "json", - }, - }, - { - name: "terraform run with --non-recursive flag", - scanOptions: &ScanOptions{ - iacType: "terraform", - policyType: []string{"all"}, - iacDirPath: testDataDir, - outputType: "json", - nonRecursive: true, - }, - wantErr: true, - }, - { - name: "normal k8s run", - scanOptions: &ScanOptions{ - policyType: []string{"k8s"}, - // kustomization.y(a)ml file not present under the dir path, error expected - iacDirPath: runTestDir, - }, - wantErr: true, - }, - { - name: "normal k8s run with successful output", - scanOptions: &ScanOptions{ - policyType: []string{"k8s"}, - iacDirPath: kustomizeTestDirPath, - outputType: "human", - }, - }, - { - name: "normal k8s run with successful output for junit-xml with passed tests", - scanOptions: &ScanOptions{ - policyType: []string{"k8s"}, - iacDirPath: kustomizeTestDirPath, - outputType: "junit-xml", - showPassedRules: true, - }, - }, - { - name: "config-only flag terraform", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacFilePath: testTerraformFilePath, - configOnly: true, - outputType: "yaml", - }, - }, - { - // test for https://github.com/accurics/terrascan/issues/718 - // a valid tfplan file is supplied, error is not expected - name: "iac type is tfplan and -f option used to specify the tfplan.json", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacType: "tfplan", - iacFilePath: testTFJSONFilePath, - outputType: "yaml", - }, - wantErr: false, - }, - { - name: "config-only flag k8s", - scanOptions: &ScanOptions{ - policyType: []string{"k8s"}, - iacDirPath: kustomizeTestDirPath, - configOnly: true, - outputType: "json", - }, - }, - { - // xml doesn't support config-only, error expected - // modify the test results when xml supports config-only - name: "config-only flag true with xml output format", + // { + // name: "normal terraform run", + // scanOptions: &ScanOptions{ + // // policy type terraform is not supported, error expected + // policyType: []string{"terraform"}, + // iacDirPath: runTestDir, + // }, + // wantErr: true, + // }, + // { + // name: "normal terraform run with successful output", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacDirPath: runTestDir, + // outputType: "json", + // }, + // }, + // { + // name: "terraform run with --non-recursive flag", + // scanOptions: &ScanOptions{ + // iacType: "terraform", + // policyType: []string{"all"}, + // iacDirPath: testDataDir, + // outputType: "json", + // nonRecursive: true, + // }, + // wantErr: true, + // }, + // { + // name: "normal k8s run", + // scanOptions: &ScanOptions{ + // policyType: []string{"k8s"}, + // // kustomization.y(a)ml file not present under the dir path, error expected + // iacDirPath: runTestDir, + // }, + // wantErr: true, + // }, + // { + // name: "normal k8s run with successful output", + // scanOptions: &ScanOptions{ + // policyType: []string{"k8s"}, + // iacDirPath: kustomizeTestDirPath, + // outputType: "human", + // }, + // }, + // { + // name: "normal k8s run with successful output for junit-xml with passed tests", + // scanOptions: &ScanOptions{ + // policyType: []string{"k8s"}, + // iacDirPath: kustomizeTestDirPath, + // outputType: "junit-xml", + // showPassedRules: true, + // }, + // }, + // { + // name: "config-only flag terraform", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacFilePath: testTerraformFilePath, + // configOnly: true, + // outputType: "yaml", + // }, + // }, + // { + // // test for https://github.com/accurics/terrascan/issues/718 + // // a valid tfplan file is supplied, error is not expected + // name: "iac type is tfplan and -f option used to specify the tfplan.json", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacType: "tfplan", + // iacFilePath: testTFJSONFilePath, + // outputType: "yaml", + // }, + // wantErr: false, + // }, + // { + // name: "config-only flag k8s", + // scanOptions: &ScanOptions{ + // policyType: []string{"k8s"}, + // iacDirPath: kustomizeTestDirPath, + // configOnly: true, + // outputType: "json", + // }, + // }, + // { + // // xml doesn't support config-only, error expected + // // modify the test results when xml supports config-only + // name: "config-only flag true with xml output format", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacFilePath: testTerraformFilePath, + // configOnly: true, + // outputType: "xml", + // }, + // wantErr: true, + // }, + // { + // name: "fail to download remote repository", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacFilePath: testTerraformFilePath, + // remoteURL: "test", + // remoteType: "test", + // }, + // wantErr: true, + // }, + // { + // name: "incorrect config file", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacDirPath: testTerraformFilePath, + // outputType: "json", + // configFile: "invalidFile", + // }, + // wantErr: true, + // }, + // { + // name: "run with skip rules", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacDirPath: runTestDir, + // outputType: "json", + // skipRules: ruleSlice, + // }, + // }, + // { + // name: "run with scan rules", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacDirPath: runTestDir, + // outputType: "yaml", + // scanRules: ruleSlice, + // }, + // }, + // { + // name: "config file with rules", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacDirPath: runTestDir, + // outputType: "yaml", + // configFile: filepath.Join(testDataDir, "configFile.toml"), + // }, + // }, + // { + // name: "scan file with remote module", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // iacFilePath: testRemoteModuleFilePath, + // outputType: "human", + // configFile: filepath.Join(testDataDir, "configFile.toml"), + // }, + // }, + // { + // name: "invalid remote type", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // remoteType: "test", + // remoteURL: "test", + // outputType: "human", + // }, + // wantErr: true, + // }, + // { + // name: "valid remote type with invalid remote url", + // scanOptions: &ScanOptions{ + // policyType: []string{"all"}, + // remoteType: "terraform-registry", + // remoteURL: "terraform-aws-modules/eks", + // outputType: "human", + // }, + // wantErr: true, + // }, + { + name: "config-with-error flag terraform", scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacFilePath: testTerraformFilePath, - configOnly: true, - outputType: "xml", + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + configWithError: true, + outputType: "json", }, - wantErr: true, - }, - { - name: "fail to download remote repository", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacFilePath: testTerraformFilePath, - remoteURL: "test", - remoteType: "test", - }, - wantErr: true, - }, - { - name: "incorrect config file", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacDirPath: testTerraformFilePath, - outputType: "json", - configFile: "invalidFile", - }, - wantErr: true, - }, - { - name: "run with skip rules", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacDirPath: runTestDir, - outputType: "json", - skipRules: ruleSlice, - }, - }, - { - name: "run with scan rules", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacDirPath: runTestDir, - outputType: "yaml", - scanRules: ruleSlice, - }, - }, - { - name: "config file with rules", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacDirPath: runTestDir, - outputType: "yaml", - configFile: filepath.Join(testDataDir, "configFile.toml"), - }, - }, - { - name: "scan file with remote module", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - iacFilePath: testRemoteModuleFilePath, - outputType: "human", - configFile: filepath.Join(testDataDir, "configFile.toml"), - }, - }, - { - name: "invalid remote type", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - remoteType: "test", - remoteURL: "test", - outputType: "human", - }, - wantErr: true, - }, - { - name: "valid remote type with invalid remote url", - scanOptions: &ScanOptions{ - policyType: []string{"all"}, - remoteType: "terraform-registry", - remoteURL: "terraform-aws-modules/eks", - outputType: "human", - }, - wantErr: true, }, } diff --git a/pkg/cli/scan.go b/pkg/cli/scan.go index 7291b67e7..a73a32dea 100644 --- a/pkg/cli/scan.go +++ b/pkg/cli/scan.go @@ -63,6 +63,7 @@ func init() { scanCmd.Flags().StringVarP(&scanOptions.remoteType, "remote-type", "r", "", "type of remote backend (git, s3, gcs, http, terraform-registry)") scanCmd.Flags().StringVarP(&scanOptions.remoteURL, "remote-url", "u", "", "url pointing to remote IaC repository") scanCmd.Flags().BoolVarP(&scanOptions.configOnly, "config-only", "", false, "will output resource config (should only be used for debugging purposes)") + scanCmd.Flags().BoolVarP(&scanOptions.configWithError, "config-with-error", "", false, "will output resource config and errors (if any)") // flag passes a string, but we normalize to bool in PreRun scanCmd.Flags().StringVar(&scanOptions.useColors, "use-colors", "auto", "color output (auto, t, f)") scanCmd.Flags().BoolVarP(&scanOptions.verbose, "verbose", "v", false, "will show violations with details (applicable for default output)") diff --git a/pkg/http-server/file-scan.go b/pkg/http-server/file-scan.go index 56b982a0e..78757f121 100644 --- a/pkg/http-server/file-scan.go +++ b/pkg/http-server/file-scan.go @@ -49,6 +49,7 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { showPassed = false findVulnerabilities = false categories = []string{} + configWithError = false ) // parse multipart form, 10 << 20 specifies maximum upload of 10 MB files @@ -133,6 +134,17 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { return } } + // read config_only from the form data + configWithErrorValue := r.FormValue("config_with_error") + if configWithErrorValue != "" { + configWithError, err = strconv.ParseBool(configWithErrorValue) + if err != nil { + errMsg := fmt.Sprintf("error while reading 'config_only' value. error: '%v'", err) + zap.S().Error(errMsg) + apiErrorResponse(w, errMsg, http.StatusBadRequest) + return + } + } // read show_passed from the form data showPassedValue := r.FormValue("show_passed") @@ -176,7 +188,7 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { apiErrorResponse(w, err.Error(), http.StatusBadRequest) return } - normalized, err := executor.Execute(configOnly) + normalized, err := executor.Execute(configOnly, configWithError) if err != nil { errMsg := fmt.Sprintf("failed to scan uploaded file. error: '%v'", err) zap.S().Error(errMsg) @@ -189,6 +201,8 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { // if config only, return resource config else return violations if configOnly { output = normalized.ResourceConfig + } else if configWithError { + output = normalized } else { if !showPassed { normalized.Violations.ViolationStore.PassedRules = nil diff --git a/pkg/http-server/remote-repo.go b/pkg/http-server/remote-repo.go index b57f05996..e63c43746 100644 --- a/pkg/http-server/remote-repo.go +++ b/pkg/http-server/remote-repo.go @@ -49,6 +49,7 @@ type scanRemoteRepoReq struct { NotificationWebhookURL string `json:"webhook_url"` NotificationWebhookToken string `json:"webhook_token"` RepoRef string `json:"repo-ref"` + ConfigWithError bool `json:"config_with_error"` } // scanRemoteRepo downloads the remote Iac repository and scans it for @@ -139,7 +140,7 @@ func (s *scanRemoteRepoReq) ScanRemoteRepo(iacType, iacVersion string, cloudType } // evaluate policies IaC for violations - results, err := executor.Execute(s.ConfigOnly) + results, err := executor.Execute(s.ConfigOnly, s.ConfigWithError) if err != nil { errMsg := fmt.Sprintf("failed to scan uploaded file. error: '%v'", err) zap.S().Error(errMsg) @@ -149,6 +150,8 @@ func (s *scanRemoteRepoReq) ScanRemoteRepo(iacType, iacVersion string, cloudType // if config only, return only config else return only violations if s.ConfigOnly { output = results.ResourceConfig + } else if s.ConfigWithError { + output = results } else { // set remote url in case remote repo is scanned if s.RemoteURL != "" { diff --git a/pkg/k8s/admission-webhook/validating-webhook.go b/pkg/k8s/admission-webhook/validating-webhook.go index 72ae1a7f9..48fffd1fe 100644 --- a/pkg/k8s/admission-webhook/validating-webhook.go +++ b/pkg/k8s/admission-webhook/validating-webhook.go @@ -209,7 +209,7 @@ func (w ValidatingWebhook) scanK8sFile(filePath string) (runtime.Output, error) return result, err } - result, err = executor.Execute(false) + result, err = executor.Execute(false, false) if err != nil { zap.S().Error("failed to scan resource object. error: '%v'", err) return result, err diff --git a/pkg/runtime/executor.go b/pkg/runtime/executor.go index 916b84637..71da6d635 100644 --- a/pkg/runtime/executor.go +++ b/pkg/runtime/executor.go @@ -30,6 +30,7 @@ import ( "github.com/accurics/terrascan/pkg/iac-providers/output" "github.com/accurics/terrascan/pkg/notifications" "github.com/accurics/terrascan/pkg/policy" + res "github.com/accurics/terrascan/pkg/results" "github.com/hashicorp/go-multierror" ) @@ -204,7 +205,7 @@ func (e *Executor) initPolicyEngines() (err error) { } // Execute validates the inputs, processes the IaC, creates json output -func (e *Executor) Execute(configOnly bool) (results Output, err error) { +func (e *Executor) Execute(configOnly, configWithError bool) (results Output, err error) { var merr *multierror.Error var resourceConfig output.AllResourceConfigs @@ -238,6 +239,15 @@ func (e *Executor) Execute(configOnly bool) (results Output, err error) { results.ResourceConfig = e.fetchVulnerabilities(&results, options) } + if configWithError { + results.Violations.ViolationStore = res.NewViolationStore() + if err := merr.ErrorOrNil(); err != nil { + sort.Sort(merr) + results.Violations.ViolationStore.AddLoadDirErrors(merr.WrappedErrors()) + } + return results, nil + } + if configOnly { return results, nil } diff --git a/pkg/runtime/executor_test.go b/pkg/runtime/executor_test.go index 871060d8a..99c9abde4 100644 --- a/pkg/runtime/executor_test.go +++ b/pkg/runtime/executor_test.go @@ -202,7 +202,7 @@ func TestExecute(t *testing.T) { for _, tt := range table { t.Run(tt.name, func(t *testing.T) { - _, gotErr := tt.executor.Execute(false) + _, gotErr := tt.executor.Execute(false, false) if !reflect.DeepEqual(gotErr, tt.wantErr) { t.Errorf("unexpected error; gotErr: '%v', wantErr: '%v'", gotErr, tt.wantErr) } diff --git a/test/e2e/help/golden/help_scan.txt b/test/e2e/help/golden/help_scan.txt index 51d152f32..6ba3da966 100644 --- a/test/e2e/help/golden/help_scan.txt +++ b/test/e2e/help/golden/help_scan.txt @@ -8,6 +8,7 @@ Usage: Flags: --categories strings list of categories of violations to be reported by terrascan (example: --categories="category1,category2") --config-only will output resource config (should only be used for debugging purposes) + --config-with-error will output resource config and errors (if any) --find-vuln fetches vulnerabilities identified in Docker images -h, --help help for scan -d, --iac-dir string path to a directory containing one or more IaC files (default ".") From aeb5695beabafc6103b75cc6615d9cd0707610f0 Mon Sep 17 00:00:00 2001 From: Nasir Rabbani Date: Wed, 9 Feb 2022 17:09:53 +0530 Subject: [PATCH 2/6] updated testcases --- pkg/cli/run_test.go | 352 ++++++++++++++-------------- pkg/http-server/file-scan.go | 2 +- pkg/http-server/file-scan_test.go | 33 +++ pkg/http-server/remote-repo_test.go | 51 ++-- 4 files changed, 242 insertions(+), 196 deletions(-) diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go index 9599c031b..86f532463 100644 --- a/pkg/cli/run_test.go +++ b/pkg/cli/run_test.go @@ -62,12 +62,12 @@ func TestRun(t *testing.T) { log.SetOutput(ioutil.Discard) } - // kustomizeTestDirPath := filepath.Join(runTestDir, "kustomize-test") + kustomizeTestDirPath := filepath.Join(runTestDir, "kustomize-test") testTerraformFilePath := filepath.Join(runTestDir, "config-only.tf") - // testRemoteModuleFilePath := filepath.Join(runTestDir, "remote-modules.tf") - // testTFJSONFilePath := filepath.Join(runTestDir, "tf-plan.json") + testRemoteModuleFilePath := filepath.Join(runTestDir, "remote-modules.tf") + testTFJSONFilePath := filepath.Join(runTestDir, "tf-plan.json") - // ruleSlice := []string{"AWS.ECR.DataSecurity.High.0579", "AWS.SecurityGroup.NetworkPortsSecurity.Low.0561"} + ruleSlice := []string{"AWS.ECR.DataSecurity.High.0579", "AWS.SecurityGroup.NetworkPortsSecurity.Low.0561"} table := []struct { name string @@ -77,178 +77,178 @@ func TestRun(t *testing.T) { want string wantErr bool }{ - // { - // name: "normal terraform run", - // scanOptions: &ScanOptions{ - // // policy type terraform is not supported, error expected - // policyType: []string{"terraform"}, - // iacDirPath: runTestDir, - // }, - // wantErr: true, - // }, - // { - // name: "normal terraform run with successful output", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacDirPath: runTestDir, - // outputType: "json", - // }, - // }, - // { - // name: "terraform run with --non-recursive flag", - // scanOptions: &ScanOptions{ - // iacType: "terraform", - // policyType: []string{"all"}, - // iacDirPath: testDataDir, - // outputType: "json", - // nonRecursive: true, - // }, - // wantErr: true, - // }, - // { - // name: "normal k8s run", - // scanOptions: &ScanOptions{ - // policyType: []string{"k8s"}, - // // kustomization.y(a)ml file not present under the dir path, error expected - // iacDirPath: runTestDir, - // }, - // wantErr: true, - // }, - // { - // name: "normal k8s run with successful output", - // scanOptions: &ScanOptions{ - // policyType: []string{"k8s"}, - // iacDirPath: kustomizeTestDirPath, - // outputType: "human", - // }, - // }, - // { - // name: "normal k8s run with successful output for junit-xml with passed tests", - // scanOptions: &ScanOptions{ - // policyType: []string{"k8s"}, - // iacDirPath: kustomizeTestDirPath, - // outputType: "junit-xml", - // showPassedRules: true, - // }, - // }, - // { - // name: "config-only flag terraform", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacFilePath: testTerraformFilePath, - // configOnly: true, - // outputType: "yaml", - // }, - // }, - // { - // // test for https://github.com/accurics/terrascan/issues/718 - // // a valid tfplan file is supplied, error is not expected - // name: "iac type is tfplan and -f option used to specify the tfplan.json", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacType: "tfplan", - // iacFilePath: testTFJSONFilePath, - // outputType: "yaml", - // }, - // wantErr: false, - // }, - // { - // name: "config-only flag k8s", - // scanOptions: &ScanOptions{ - // policyType: []string{"k8s"}, - // iacDirPath: kustomizeTestDirPath, - // configOnly: true, - // outputType: "json", - // }, - // }, - // { - // // xml doesn't support config-only, error expected - // // modify the test results when xml supports config-only - // name: "config-only flag true with xml output format", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacFilePath: testTerraformFilePath, - // configOnly: true, - // outputType: "xml", - // }, - // wantErr: true, - // }, - // { - // name: "fail to download remote repository", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacFilePath: testTerraformFilePath, - // remoteURL: "test", - // remoteType: "test", - // }, - // wantErr: true, - // }, - // { - // name: "incorrect config file", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacDirPath: testTerraformFilePath, - // outputType: "json", - // configFile: "invalidFile", - // }, - // wantErr: true, - // }, - // { - // name: "run with skip rules", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacDirPath: runTestDir, - // outputType: "json", - // skipRules: ruleSlice, - // }, - // }, - // { - // name: "run with scan rules", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacDirPath: runTestDir, - // outputType: "yaml", - // scanRules: ruleSlice, - // }, - // }, - // { - // name: "config file with rules", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacDirPath: runTestDir, - // outputType: "yaml", - // configFile: filepath.Join(testDataDir, "configFile.toml"), - // }, - // }, - // { - // name: "scan file with remote module", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // iacFilePath: testRemoteModuleFilePath, - // outputType: "human", - // configFile: filepath.Join(testDataDir, "configFile.toml"), - // }, - // }, - // { - // name: "invalid remote type", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // remoteType: "test", - // remoteURL: "test", - // outputType: "human", - // }, - // wantErr: true, - // }, - // { - // name: "valid remote type with invalid remote url", - // scanOptions: &ScanOptions{ - // policyType: []string{"all"}, - // remoteType: "terraform-registry", - // remoteURL: "terraform-aws-modules/eks", - // outputType: "human", - // }, - // wantErr: true, - // }, + { + name: "normal terraform run", + scanOptions: &ScanOptions{ + // policy type terraform is not supported, error expected + policyType: []string{"terraform"}, + iacDirPath: runTestDir, + }, + wantErr: true, + }, + { + name: "normal terraform run with successful output", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacDirPath: runTestDir, + outputType: "json", + }, + }, + { + name: "terraform run with --non-recursive flag", + scanOptions: &ScanOptions{ + iacType: "terraform", + policyType: []string{"all"}, + iacDirPath: testDataDir, + outputType: "json", + nonRecursive: true, + }, + wantErr: true, + }, + { + name: "normal k8s run", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + // kustomization.y(a)ml file not present under the dir path, error expected + iacDirPath: runTestDir, + }, + wantErr: true, + }, + { + name: "normal k8s run with successful output", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + iacDirPath: kustomizeTestDirPath, + outputType: "human", + }, + }, + { + name: "normal k8s run with successful output for junit-xml with passed tests", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + iacDirPath: kustomizeTestDirPath, + outputType: "junit-xml", + showPassedRules: true, + }, + }, + { + name: "config-only flag terraform", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + configOnly: true, + outputType: "yaml", + }, + }, + { + // test for https://github.com/accurics/terrascan/issues/718 + // a valid tfplan file is supplied, error is not expected + name: "iac type is tfplan and -f option used to specify the tfplan.json", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacType: "tfplan", + iacFilePath: testTFJSONFilePath, + outputType: "yaml", + }, + wantErr: false, + }, + { + name: "config-only flag k8s", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + iacDirPath: kustomizeTestDirPath, + configOnly: true, + outputType: "json", + }, + }, + { + // xml doesn't support config-only, error expected + // modify the test results when xml supports config-only + name: "config-only flag true with xml output format", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + configOnly: true, + outputType: "xml", + }, + wantErr: true, + }, + { + name: "fail to download remote repository", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + remoteURL: "test", + remoteType: "test", + }, + wantErr: true, + }, + { + name: "incorrect config file", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacDirPath: testTerraformFilePath, + outputType: "json", + configFile: "invalidFile", + }, + wantErr: true, + }, + { + name: "run with skip rules", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacDirPath: runTestDir, + outputType: "json", + skipRules: ruleSlice, + }, + }, + { + name: "run with scan rules", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacDirPath: runTestDir, + outputType: "yaml", + scanRules: ruleSlice, + }, + }, + { + name: "config file with rules", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacDirPath: runTestDir, + outputType: "yaml", + configFile: filepath.Join(testDataDir, "configFile.toml"), + }, + }, + { + name: "scan file with remote module", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testRemoteModuleFilePath, + outputType: "human", + configFile: filepath.Join(testDataDir, "configFile.toml"), + }, + }, + { + name: "invalid remote type", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + remoteType: "test", + remoteURL: "test", + outputType: "human", + }, + wantErr: true, + }, + { + name: "valid remote type with invalid remote url", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + remoteType: "terraform-registry", + remoteURL: "terraform-aws-modules/eks", + outputType: "human", + }, + wantErr: true, + }, { name: "config-with-error flag terraform", scanOptions: &ScanOptions{ diff --git a/pkg/http-server/file-scan.go b/pkg/http-server/file-scan.go index 78757f121..81e1dea9c 100644 --- a/pkg/http-server/file-scan.go +++ b/pkg/http-server/file-scan.go @@ -139,7 +139,7 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { if configWithErrorValue != "" { configWithError, err = strconv.ParseBool(configWithErrorValue) if err != nil { - errMsg := fmt.Sprintf("error while reading 'config_only' value. error: '%v'", err) + errMsg := fmt.Sprintf("error while reading 'config_with_error' value. error: '%v'", err) zap.S().Error(errMsg) apiErrorResponse(w, errMsg, http.StatusBadRequest) return diff --git a/pkg/http-server/file-scan_test.go b/pkg/http-server/file-scan_test.go index 81af1f44d..789f55f9b 100644 --- a/pkg/http-server/file-scan_test.go +++ b/pkg/http-server/file-scan_test.go @@ -44,6 +44,8 @@ func TestUpload(t *testing.T) { findVulnerabilities bool notificationWebhookURL string notificationWebhookToken string + configWithError bool + invalidConfigWithError bool }{ { name: "valid file scan", @@ -273,6 +275,25 @@ func TestUpload(t *testing.T) { notificationWebhookURL: "https://httpbin.org/post", notificationWebhookToken: "token", }, + { + name: "test for config with erorr invalid", + path: testFilePath, + param: testParamName, + iacType: testIacType, + cloudType: testCloudType, + wantStatus: http.StatusBadRequest, + invalidConfigWithError: true, + }, + { + name: "test for config with eror", + path: testFilePath, + param: testParamName, + iacType: testIacType, + cloudType: testCloudType, + wantStatus: http.StatusOK, + invalidConfigWithError: false, + configWithError: true, + }, } for _, tt := range table { @@ -378,6 +399,18 @@ func TestUpload(t *testing.T) { } } + if !tt.invalidConfigWithError { + if err = writer.WriteField("config_with_error", strconv.FormatBool(tt.configWithError)); err != nil { + writer.Close() + t.Error(err) + } + } else { + if err = writer.WriteField("config_with_error", "invalid"); err != nil { + writer.Close() + t.Error(err) + } + } + writer.Close() // http request of the type "/v1/{iacType}/{iacVersion}/{cloudType}/file/scan" diff --git a/pkg/http-server/remote-repo_test.go b/pkg/http-server/remote-repo_test.go index 429d18acf..37f4aa4c8 100644 --- a/pkg/http-server/remote-repo_test.go +++ b/pkg/http-server/remote-repo_test.go @@ -92,18 +92,19 @@ func TestScanRemoteRepoHandler(t *testing.T) { testCloudType := "aws" table := []struct { - name string - iacType string - iacVersion string - cloudType string - remoteURL string - remoteType string - scanRules []string - skipRules []string - showPassed bool - configOnly bool - nonRecursive bool - wantStatus int + name string + iacType string + iacVersion string + cloudType string + remoteURL string + remoteType string + scanRules []string + skipRules []string + showPassed bool + configOnly bool + configWithError bool + nonRecursive bool + wantStatus int }{ { name: "empty url and type", @@ -174,6 +175,17 @@ func TestScanRemoteRepoHandler(t *testing.T) { configOnly: true, wantStatus: http.StatusOK, }, + { + name: "test show config with error", + iacType: testIacType, + iacVersion: testIacVersion, + cloudType: testCloudType, + remoteURL: validRepo, + remoteType: "git", + showPassed: false, + configWithError: true, + wantStatus: http.StatusOK, + }, } for _, tt := range table { @@ -186,13 +198,14 @@ func TestScanRemoteRepoHandler(t *testing.T) { // request body s := scanRemoteRepoReq{ - RemoteURL: tt.remoteURL, - RemoteType: tt.remoteType, - ScanRules: tt.scanRules, - SkipRules: tt.skipRules, - ShowPassed: tt.showPassed, - ConfigOnly: tt.configOnly, - NonRecursive: tt.nonRecursive, + RemoteURL: tt.remoteURL, + RemoteType: tt.remoteType, + ScanRules: tt.scanRules, + SkipRules: tt.skipRules, + ShowPassed: tt.showPassed, + ConfigOnly: tt.configOnly, + ConfigWithError: tt.configWithError, + NonRecursive: tt.nonRecursive, } reqBody, _ := json.Marshal(s) From 5119db125fdbd38b21f15873c36b500f246be043 Mon Sep 17 00:00:00 2001 From: Nasir Rabbani Date: Wed, 9 Feb 2022 18:36:46 +0530 Subject: [PATCH 3/6] added more tests --- pkg/runtime/executor_test.go | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/pkg/runtime/executor_test.go b/pkg/runtime/executor_test.go index 99c9abde4..f51d722c2 100644 --- a/pkg/runtime/executor_test.go +++ b/pkg/runtime/executor_test.go @@ -116,9 +116,11 @@ func TestExecute(t *testing.T) { // TODO: add tests to validate output of Execute() table := []struct { - name string - executor Executor - wantErr error + name string + configOnly bool + configWithError bool + executor Executor + wantErr error }{ { name: "test LoadIacDir error", @@ -198,11 +200,30 @@ func TestExecute(t *testing.T) { }, wantErr: nil, }, + { + name: "has scan errors with all the iac providers", + executor: Executor{ + dirPath: testDir, + iacType: "all", + iacProviders: []iacProvider.IacProvider{MockIacProvider{err: errMockLoadIacDir}}, + }, + wantErr: nil, + }, + { + name: "test config with error", + configWithError: true, + executor: Executor{ + dirPath: testDir, + iacType: "terraform", + iacProviders: []iacProvider.IacProvider{MockIacProvider{err: errMockLoadIacDir}}, + }, + wantErr: nil, + }, } for _, tt := range table { t.Run(tt.name, func(t *testing.T) { - _, gotErr := tt.executor.Execute(false, false) + _, gotErr := tt.executor.Execute(tt.configOnly, tt.configWithError) if !reflect.DeepEqual(gotErr, tt.wantErr) { t.Errorf("unexpected error; gotErr: '%v', wantErr: '%v'", gotErr, tt.wantErr) } From e10d547cb91a6e3e3aab52157d31433f9fc3b87e Mon Sep 17 00:00:00 2001 From: Nasir Rabbani Date: Wed, 9 Feb 2022 22:39:20 +0530 Subject: [PATCH 4/6] code review fixes --- pkg/cli/run.go | 15 +++++++-------- pkg/cli/run_test.go | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/pkg/cli/run.go b/pkg/cli/run.go index 4c5d2287b..ae5795cb9 100644 --- a/pkg/cli/run.go +++ b/pkg/cli/run.go @@ -32,8 +32,8 @@ import ( ) const ( - humanOutputFormat = "human" - sarifOutputFormat = "sarif" + yamlOutputFormat = "yaml" + jsonOutputFormat = "json" ) // ScanOptions represents scan command and its optional flags @@ -151,13 +151,12 @@ func (s *ScanOptions) Init() error { // validate config only for human readable output // rest command options are validated by the executor func (s ScanOptions) validate() error { - // human readable output doesn't support --config-only flag - // if --config-only flag is set, then exit with an error + // human readable output doesn't support --config-only and --config-with-error flag + // if --config-only/--config-with-error flag is set, then exit with an error // asking the user to use yaml or json output format - if s.configOnly && strings.EqualFold(s.outputType, humanOutputFormat) { - return errors.New("please use yaml or json output format when using --config-only flag") + if (s.configOnly || s.configWithError) && !(strings.EqualFold(s.outputType, yamlOutputFormat) || strings.EqualFold(s.outputType, jsonOutputFormat)) { + return errors.New("please use yaml or json output format when using --config-only or --config-with-error flags") } - return nil } @@ -227,7 +226,7 @@ func (s *ScanOptions) Run() error { return err } - if !s.configOnly && flag.Lookup("test.v") == nil && !s.configWithError { + if !s.configOnly && flag.Lookup("test.v") == nil { os.RemoveAll(tempDir) exitCode := getExitCode(results) if exitCode != 0 { diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go index 86f532463..98d292bf0 100644 --- a/pkg/cli/run_test.go +++ b/pkg/cli/run_test.go @@ -484,9 +484,10 @@ func TestScanOptionsInitColor(t *testing.T) { func TestScanOptionsInit(t *testing.T) { type fields struct { - configOnly bool - outputType string - useColors string + configOnly bool + configWithError bool + outputType string + useColors string } tests := []struct { name string @@ -510,13 +511,41 @@ func TestScanOptionsInit(t *testing.T) { configOnly: false, }, }, + { + name: "init fail for --config-with-error with human readable output", + fields: fields{ + useColors: "auto", + outputType: "human", + configWithError: true, + }, + wantErr: true, + }, + { + name: "init fail for --config-with-error with yaml readable output", + fields: fields{ + useColors: "auto", + outputType: "yaml", + configWithError: true, + }, + wantErr: false, + }, + { + name: "init fail for --config-with-error with json readable output", + fields: fields{ + useColors: "auto", + outputType: "json", + configWithError: true, + }, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &ScanOptions{ - configOnly: tt.fields.configOnly, - outputType: tt.fields.outputType, - useColors: tt.fields.useColors, + configOnly: tt.fields.configOnly, + configWithError: tt.fields.configWithError, + outputType: tt.fields.outputType, + useColors: tt.fields.useColors, } if err := s.Init(); (err != nil) != tt.wantErr { t.Errorf("ScanOptions.Init() error = %v, wantErr %v", err, tt.wantErr) From bd05ee00c078e4cb31c54913ee7dc64ac6df3d65 Mon Sep 17 00:00:00 2001 From: Nasir Rabbani Date: Thu, 10 Feb 2022 10:51:08 +0530 Subject: [PATCH 5/6] fixed e2e tests --- test/e2e/scan/scan_config_only_test.go | 8 +- test/e2e/scan/scan_config_with_error_test.go | 132 +++++++++++++++++++ 2 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 test/e2e/scan/scan_config_with_error_test.go diff --git a/test/e2e/scan/scan_config_only_test.go b/test/e2e/scan/scan_config_only_test.go index 4831401c9..26a2297a0 100644 --- a/test/e2e/scan/scan_config_only_test.go +++ b/test/e2e/scan/scan_config_only_test.go @@ -52,7 +52,7 @@ var _ = Describe("Scan With Config Only Flag", func() { Context("it doesn't support --config-only flag", func() { Context("human readable output format is the default output format", func() { It("should result in an error and exit with status code 1", func() { - errString := "please use yaml or json output format when using --config-only flag" + errString := "please use yaml or json output format when using --config-only or --config-with-error flags" scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-only"} scanUtils.RunScanAndAssertErrorMessage(terrascanBinaryPath, helper.ExitCodeOne, scanUtils.ScanTimeout, errString, outWriter, errWriter, scanArgs...) }) @@ -63,7 +63,7 @@ var _ = Describe("Scan With Config Only Flag", func() { When("output type is xml", func() { Context("it doesn't support --config-only flag", func() { It("should result in an error and exit with status code 1", func() { - errString := "failed to write XML output. error: 'xml: unsupported type: output.AllResourceConfigs'" + errString := "please use yaml or json output format when using --config-only or --config-with-error flags" scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-only", "-o", "xml"} scanUtils.RunScanAndAssertErrorMessage(terrascanBinaryPath, helper.ExitCodeOne, scanUtils.ScanTimeout, errString, outWriter, errWriter, scanArgs...) }) @@ -73,7 +73,7 @@ var _ = Describe("Scan With Config Only Flag", func() { When("output type is junit-xml", func() { Context("it doesn't support --config-only flag", func() { It("should result in an error and exit with status code 1", func() { - errString := "incorrect input for JunitXML writer, supported type is policy.EngineOutput" + errString := "please use yaml or json output format when using --config-only or --config-with-error flags" scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-only", "-o", "junit-xml"} scanUtils.RunScanAndAssertErrorMessage(terrascanBinaryPath, helper.ExitCodeOne, scanUtils.ScanTimeout, errString, outWriter, errWriter, scanArgs...) }) @@ -81,7 +81,7 @@ var _ = Describe("Scan With Config Only Flag", func() { }) }) - Describe("scan command is run using the --config-only flag for unsupported output types", func() { + Describe("scan command is run using the --config-only flag for supported output types", func() { Context("for terraform files", func() { When("output type is json", func() { Context("it supports --config-only flag", func() { diff --git a/test/e2e/scan/scan_config_with_error_test.go b/test/e2e/scan/scan_config_with_error_test.go new file mode 100644 index 000000000..8aee6eca9 --- /dev/null +++ b/test/e2e/scan/scan_config_with_error_test.go @@ -0,0 +1,132 @@ +/* + Copyright (C) 2022 Accurics, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package scan_test + +import ( + "path/filepath" + + scanUtils "github.com/accurics/terrascan/test/e2e/scan" + "github.com/accurics/terrascan/test/helper" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/gbytes" + "github.com/onsi/gomega/gexec" +) + +var _ = Describe("Scan With Config With Error Flag", func() { + + BeforeEach(func() { + outWriter = gbytes.NewBuffer() + errWriter = gbytes.NewBuffer() + }) + + AfterEach(func() { + outWriter = nil + errWriter = nil + }) + + var iacDir string + var err error + iacDir, err = filepath.Abs(filepath.Join(awsIacRelPath, "aws_ami_violation")) + + It("should not error out while getting absolute path", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + Describe("scan command is run using the --config-with-error flag for unsupported output types", func() { + When("output type is human readable format", func() { + Context("it doesn't support --config-with-error flag", func() { + Context("human readable output format is the default output format", func() { + It("should result in an error and exit with status code 1", func() { + errString := "please use yaml or json output format when using --config-only or --config-with-error flags" + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error"} + scanUtils.RunScanAndAssertErrorMessage(terrascanBinaryPath, helper.ExitCodeOne, scanUtils.ScanTimeout, errString, outWriter, errWriter, scanArgs...) + }) + }) + }) + }) + + When("output type is xml", func() { + Context("it doesn't support --config-with-error flag", func() { + It("should result in an error and exit with status code 1", func() { + errString := "please use yaml or json output format when using --config-only or --config-with-error flags" + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error", "-o", "xml"} + scanUtils.RunScanAndAssertErrorMessage(terrascanBinaryPath, helper.ExitCodeOne, scanUtils.ScanTimeout, errString, outWriter, errWriter, scanArgs...) + }) + }) + }) + + When("output type is junit-xml", func() { + Context("it doesn't support --config-with-error flag", func() { + It("should result in an error and exit with status code 1", func() { + errString := "please use yaml or json output format when using --config-only or --config-with-error flags" + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error", "-o", "junit-xml"} + scanUtils.RunScanAndAssertErrorMessage(terrascanBinaryPath, helper.ExitCodeOne, scanUtils.ScanTimeout, errString, outWriter, errWriter, scanArgs...) + }) + }) + }) + }) + + Describe("scan command is run using the --config-with-error flag for supported output types", func() { + Context("for terraform files", func() { + When("output type is json", func() { + Context("it supports --config-with-error flag", func() { + It("should display config json and exit with status code 4", func() { + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error", "-o", "json"} + session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) + Eventually(session, scanUtils.ScanTimeout).Should(gexec.Exit(helper.ExitCodeFour)) + }) + }) + }) + + When("output type is yaml", func() { + Context("it supports --config-with-error flag", func() { + It("should display config json and exit with status code 4", func() { + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error", "-o", "yaml"} + session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) + Eventually(session, scanUtils.ScanTimeout).Should(gexec.Exit(helper.ExitCodeFour)) + }) + }) + }) + }) + + Context("for yaml files", func() { + JustBeforeEach(func() { + iacDir, err = filepath.Abs(filepath.Join(k8sIacRelPath, "kubernetes_ingress_violation")) + }) + When("output type is json", func() { + Context("it supports --config-with-error flag", func() { + It("should display config json and exit with status code 0", func() { + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error", "-o", "json", "-i", "k8s"} + session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) + Eventually(session, scanUtils.ScanTimeout).Should(gexec.Exit(helper.ExitCodeZero)) + }) + }) + }) + + When("output type is yaml", func() { + Context("it supports --config-with-error flag", func() { + It("should display config json and exit with status code 0", func() { + scanArgs := []string{scanUtils.ScanCommand, "-d", iacDir, "--config-with-error", "-o", "yaml", "-i", "k8s"} + session = helper.RunCommand(terrascanBinaryPath, outWriter, errWriter, scanArgs...) + Eventually(session, scanUtils.ScanTimeout).Should(gexec.Exit(helper.ExitCodeZero)) + }) + }) + }) + }) + }) +}) From 71d19b2880585fca7ccc891077080ea0791715b2 Mon Sep 17 00:00:00 2001 From: Nasir Rabbani Date: Thu, 10 Feb 2022 14:39:05 +0530 Subject: [PATCH 6/6] code review fixes --- pkg/cli/run_test.go | 4 ++-- pkg/http-server/file-scan.go | 10 +++++----- pkg/http-server/remote-repo.go | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go index 98d292bf0..0e5595613 100644 --- a/pkg/cli/run_test.go +++ b/pkg/cli/run_test.go @@ -521,7 +521,7 @@ func TestScanOptionsInit(t *testing.T) { wantErr: true, }, { - name: "init fail for --config-with-error with yaml readable output", + name: "init success for --config-with-error with yaml readable output", fields: fields{ useColors: "auto", outputType: "yaml", @@ -530,7 +530,7 @@ func TestScanOptionsInit(t *testing.T) { wantErr: false, }, { - name: "init fail for --config-with-error with json readable output", + name: "init success for --config-with-error with json readable output", fields: fields{ useColors: "auto", outputType: "json", diff --git a/pkg/http-server/file-scan.go b/pkg/http-server/file-scan.go index 81e1dea9c..992e7d8e3 100644 --- a/pkg/http-server/file-scan.go +++ b/pkg/http-server/file-scan.go @@ -134,7 +134,7 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { return } } - // read config_only from the form data + // read config_with_error from the form data configWithErrorValue := r.FormValue("config_with_error") if configWithErrorValue != "" { configWithError, err = strconv.ParseBool(configWithErrorValue) @@ -198,11 +198,11 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) { var output interface{} - // if config only, return resource config else return violations - if configOnly { - output = normalized.ResourceConfig - } else if configWithError { + // if config-with-error return config as well as dir errors,for config only, return resource config else return violations + if configWithError { output = normalized + } else if configOnly { + output = normalized.ResourceConfig } else { if !showPassed { normalized.Violations.ViolationStore.PassedRules = nil diff --git a/pkg/http-server/remote-repo.go b/pkg/http-server/remote-repo.go index e63c43746..799ec1f4e 100644 --- a/pkg/http-server/remote-repo.go +++ b/pkg/http-server/remote-repo.go @@ -147,11 +147,11 @@ func (s *scanRemoteRepoReq) ScanRemoteRepo(iacType, iacVersion string, cloudType return output, isAdmissionDenied, err } - // if config only, return only config else return only violations - if s.ConfigOnly { - output = results.ResourceConfig - } else if s.ConfigWithError { + // if config-with-error return config as well as dir errors,for config only, return resource config else return violations + if s.ConfigWithError { output = results + } else if s.ConfigOnly { + output = results.ResourceConfig } else { // set remote url in case remote repo is scanned if s.RemoteURL != "" {