1
0
mirror of https://github.com/securego/gosec.git synced 2024-12-30 21:19:46 +02:00

Add sonarqube output

This commit is contained in:
kencrawford 2019-03-11 16:13:48 -04:00 committed by Grant Murphy
parent c5e6c4aedd
commit ddfe54d0a0
3 changed files with 84 additions and 7 deletions

View File

@ -65,7 +65,7 @@ var (
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
// format output
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, yaml, csv, junit-xml, html, or text")
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, yaml, csv, junit-xml, html, sonarqube, or text")
// output file
flagOutput = flag.String("out", "", "Set output file for results")
@ -165,19 +165,19 @@ func loadRules(include, exclude string) rules.RuleList {
return rules.Generate(filters...)
}
func saveOutput(filename, format string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error {
func saveOutput(filename, format, rootPath string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error {
if filename != "" {
outfile, err := os.Create(filename)
if err != nil {
return err
}
defer outfile.Close()
err = output.CreateReport(outfile, format, issues, metrics, errors)
err = output.CreateReport(outfile, format, rootPath, issues, metrics, errors)
if err != nil {
return err
}
} else {
err := output.CreateReport(os.Stdout, format, issues, metrics, errors)
err := output.CreateReport(os.Stdout, format, rootPath, issues, metrics, errors)
if err != nil {
return err
}
@ -318,6 +318,7 @@ func main() {
if *flagBuildTags != "" {
buildTags = strings.Split(*flagBuildTags, ",")
}
if err := analyzer.Process(buildTags, packages...); err != nil {
logger.Fatal(err)
}
@ -342,9 +343,9 @@ func main() {
if !issuesFound && *flagQuiet {
os.Exit(0)
}
rootPath := packages[0]
// Create output report
if err := saveOutput(*flagOutput, *flagFormat, issues, metrics, errors); err != nil {
if err := saveOutput(*flagOutput, *flagFormat, rootPath, issues, metrics, errors); err != nil {
logger.Fatal(err)
}

View File

@ -20,6 +20,8 @@ import (
"encoding/xml"
htmlTemplate "html/template"
"io"
"strconv"
"strings"
plainTemplate "text/template"
"github.com/securego/gosec"
@ -71,7 +73,7 @@ type reportInfo struct {
// CreateReport generates a report based for the supplied issues and metrics given
// the specified format. The formats currently accepted are: json, csv, html and text.
func CreateReport(w io.Writer, format string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error {
func CreateReport(w io.Writer, format, rootPath string, issues []*gosec.Issue, metrics *gosec.Metrics, errors map[string][]gosec.Error) error {
data := &reportInfo{
Errors: errors,
Issues: issues,
@ -91,12 +93,50 @@ func CreateReport(w io.Writer, format string, issues []*gosec.Issue, metrics *go
err = reportFromHTMLTemplate(w, html, data)
case "text":
err = reportFromPlaintextTemplate(w, text, data)
case "sonarqube":
err = reportSonarqube(rootPath, w, data)
default:
err = reportFromPlaintextTemplate(w, text, data)
}
return err
}
func reportSonarqube(rootPath string, w io.Writer, data *reportInfo) error {
var sonarIssues []sonarIssue
for _, issue := range data.Issues {
lines := strings.Split(issue.Line, "-")
startLine, _ := strconv.Atoi(lines[0])
endLine := startLine
if len(lines) > 1 {
endLine, _ = strconv.Atoi(lines[1])
}
s := sonarIssue{
EngineId: "gosec",
RuleId: issue.RuleID,
PrimaryLocation: location{
Message: issue.What,
FilePath: strings.Replace(issue.File, rootPath+"/", "", 1),
TextRange: textRange{StartLine: startLine, EndLine: endLine},
},
Type: "VULNERABILITY",
Severity: getSonarSeverity(issue.Severity.String()),
EffortMinutes: 5,
}
sonarIssues = append(sonarIssues, s)
}
raw, err := json.MarshalIndent(sonarIssues, "", "\t")
if err != nil {
panic(err)
}
_, err = w.Write(raw)
if err != nil {
panic(err)
}
return err
}
func reportJSON(w io.Writer, data *reportInfo) error {
raw, err := json.MarshalIndent(data, "", "\t")
if err != nil {

View File

@ -0,0 +1,36 @@
package output
type textRange struct {
StartLine int `json:"startLine"`
EndLine int `json:"endLine"`
StartColumn int `json:"startColumn,omitempty"`
EtartColumn int `json:"endColumn,omitempty"`
}
type location struct {
Message string `json:"message"`
FilePath string `json:"filePath"`
TextRange textRange `json:"textRange,omitempty"`
}
type sonarIssue struct {
EngineId string `json:"engineId"`
RuleId string `json:"ruleId"`
PrimaryLocation location `json:"primaryLocation"`
Type string `json:"type"`
Severity string `json:"severity"`
EffortMinutes int `json:"effortMinutes"`
SecondaryLocations []location `json:"secondaryLocations,omitempty"`
}
func getSonarSeverity(s string) string {
switch s {
case "LOW":
return "MINOR"
case "MEDIUM":
return "MAJOR"
case "HIGH":
return "BLOCKER"
default:
return "INFO"
}
}