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:
parent
c5e6c4aedd
commit
ddfe54d0a0
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
36
output/sonarqube_format.go
Normal file
36
output/sonarqube_format.go
Normal 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"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user