From a8b633f124f712e465ac2d7ee0e992b274cc40a6 Mon Sep 17 00:00:00 2001 From: Shreyas Subhedar Date: Mon, 10 May 2021 14:14:55 +0530 Subject: [PATCH] Adding stdout and verbose flags and refactor how the report is saved --- README.md | 10 +++++++ cmd/gosec/main.go | 71 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 92d0d37..54f9f3d 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,16 @@ file. The output format is controlled by the `-fmt` flag, and the output file is $ gosec -fmt=json -out=results.json *.go ``` +Results will be reported to stdout as well as to the provided output file by `-stdout` flag. The `-verbose` flag overrides the +output format when stdout the results while saving them in the output file +```bash +# Write output in json format to results.json as well as stdout +$ gosec -fmt=json -out=results.json -stdout *.go + +# Overrides the output format to 'text' when stdout the results, while writing it to results.json +$ gosec -fmt=json -out=results.json -stdout -verbose=text *.go +``` + **Note:** gosec generates the [generic issue import format](https://docs.sonarqube.org/latest/analysis/generic-issue/) for SonarQube, and a report has to be imported into SonarQube using `sonar.externalIssuesReportPaths=path/to/gosec-report.json`. ## Development diff --git a/cmd/gosec/main.go b/cmd/gosec/main.go index 72dca57..acc649d 100644 --- a/cmd/gosec/main.go +++ b/cmd/gosec/main.go @@ -117,6 +117,12 @@ var ( // print version and quit with exit code 0 flagVersion = flag.Bool("version", false, "Print version and quit with exit code 0") + // stdout the results as well as write it in the output file + flagStdOut = flag.Bool("stdout", false, "Stdout the results as well as write it in the output file") + + // overrides the output format when stdout the results while saving them in the output file + flagVerbose = flag.String("verbose", "", "Overrides the output format when stdout the results while saving them in the output file.\nValid options are: json, yaml, csv, junit-xml, html, sonarqube, golint, sarif or text") + // exlude the folders from scan flagDirsExclude arrayFlags @@ -187,30 +193,45 @@ func loadRules(include, exclude string) rules.RuleList { return rules.Generate(filters...) } -func saveOutput(filename, format string, color bool, paths []string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error { +func getRootPaths(paths []string) []string { rootPaths := []string{} for _, path := range paths { rootPath, err := gosec.RootPath(path) if err != nil { - return fmt.Errorf("failed to get the root path of the projects: %s", err) + logger.Fatal(fmt.Errorf("failed to get the root path of the projects: %s", err)) } rootPaths = append(rootPaths, rootPath) } - if filename != "" { - outfile, err := os.Create(filename) - if err != nil { - return err - } - defer outfile.Close() // #nosec G307 - err = report.CreateReport(outfile, format, color, rootPaths, issues, metrics, errors) - if err != nil { - return err - } - } else { - err := report.CreateReport(os.Stdout, format, color, rootPaths, issues, metrics, errors) - if err != nil { - return err - } + return rootPaths +} + +func getPrintedFormat(format string, verbose string) string { + var fileFormat = format + if format != "" && verbose != "" { + fileFormat = verbose + } + return fileFormat +} + +func printReport(format string, color bool, rootPaths []string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error { + + err := report.CreateReport(os.Stdout, format, color, rootPaths, issues, metrics, errors) + if err != nil { + return err + } + return nil +} + +func saveReport(filename, format string, color bool, rootPaths []string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error { + + outfile, err := os.Create(filename) + if err != nil { + return err + } + defer outfile.Close() // #nosec G307 + err = report.CreateReport(outfile, format, color, rootPaths, issues, metrics, errors) + if err != nil { + return err } return nil } @@ -291,7 +312,7 @@ func main() { // Color flag is allowed for text format var color bool - if *flagFormat == "text" { + if *flagFormat == "text" || *flagVerbose == "text" { color = true } @@ -363,8 +384,18 @@ func main() { } // Create output report - if err := saveOutput(*flagOutput, *flagFormat, color, flag.Args(), issues, metrics, errors); err != nil { - logger.Fatal(err) + rootPaths := getRootPaths(flag.Args()) + + if *flagOutput == "" || *flagStdOut { + var fileFormat = getPrintedFormat(*flagOutput, *flagVerbose) + if err := printReport(fileFormat, color, rootPaths, issues, metrics, errors); err != nil { + logger.Fatal((err)) + } + } + if *flagOutput != "" { + if err := saveReport(*flagOutput, *flagFormat, color, rootPaths, issues, metrics, errors); err != nil { + logger.Fatal(err) + } } // Finalize logging