mirror of
https://github.com/securego/gosec.git
synced 2025-11-27 22:28:20 +02:00
Add sonarqube output
This commit is contained in:
committed by
Grant Murphy
parent
c5e6c4aedd
commit
ddfe54d0a0
@@ -65,7 +65,7 @@ var (
|
|||||||
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
|
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
|
||||||
|
|
||||||
// format output
|
// 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
|
// output file
|
||||||
flagOutput = flag.String("out", "", "Set output file for results")
|
flagOutput = flag.String("out", "", "Set output file for results")
|
||||||
@@ -165,19 +165,19 @@ func loadRules(include, exclude string) rules.RuleList {
|
|||||||
return rules.Generate(filters...)
|
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 != "" {
|
if filename != "" {
|
||||||
outfile, err := os.Create(filename)
|
outfile, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer outfile.Close()
|
defer outfile.Close()
|
||||||
err = output.CreateReport(outfile, format, issues, metrics, errors)
|
err = output.CreateReport(outfile, format, rootPath, issues, metrics, errors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := output.CreateReport(os.Stdout, format, issues, metrics, errors)
|
err := output.CreateReport(os.Stdout, format, rootPath, issues, metrics, errors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -318,6 +318,7 @@ func main() {
|
|||||||
if *flagBuildTags != "" {
|
if *flagBuildTags != "" {
|
||||||
buildTags = strings.Split(*flagBuildTags, ",")
|
buildTags = strings.Split(*flagBuildTags, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := analyzer.Process(buildTags, packages...); err != nil {
|
if err := analyzer.Process(buildTags, packages...); err != nil {
|
||||||
logger.Fatal(err)
|
logger.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -342,9 +343,9 @@ func main() {
|
|||||||
if !issuesFound && *flagQuiet {
|
if !issuesFound && *flagQuiet {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
rootPath := packages[0]
|
||||||
// Create output report
|
// 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)
|
logger.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import (
|
|||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
htmlTemplate "html/template"
|
htmlTemplate "html/template"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
plainTemplate "text/template"
|
plainTemplate "text/template"
|
||||||
|
|
||||||
"github.com/securego/gosec"
|
"github.com/securego/gosec"
|
||||||
@@ -71,7 +73,7 @@ type reportInfo struct {
|
|||||||
|
|
||||||
// CreateReport generates a report based for the supplied issues and metrics given
|
// 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.
|
// 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{
|
data := &reportInfo{
|
||||||
Errors: errors,
|
Errors: errors,
|
||||||
Issues: issues,
|
Issues: issues,
|
||||||
@@ -91,12 +93,50 @@ func CreateReport(w io.Writer, format string, issues []*gosec.Issue, metrics *go
|
|||||||
err = reportFromHTMLTemplate(w, html, data)
|
err = reportFromHTMLTemplate(w, html, data)
|
||||||
case "text":
|
case "text":
|
||||||
err = reportFromPlaintextTemplate(w, text, data)
|
err = reportFromPlaintextTemplate(w, text, data)
|
||||||
|
case "sonarqube":
|
||||||
|
err = reportSonarqube(rootPath, w, data)
|
||||||
default:
|
default:
|
||||||
err = reportFromPlaintextTemplate(w, text, data)
|
err = reportFromPlaintextTemplate(w, text, data)
|
||||||
}
|
}
|
||||||
return err
|
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 {
|
func reportJSON(w io.Writer, data *reportInfo) error {
|
||||||
raw, err := json.MarshalIndent(data, "", "\t")
|
raw, err := json.MarshalIndent(data, "", "\t")
|
||||||
if err != nil {
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user