Migrate sonar types in a dedicated package (#604)

This commit is contained in:
Matthieu MOREL 2021-05-05 16:21:53 +02:00 committed by GitHub
parent b519743da6
commit 37639537ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 125 additions and 93 deletions

View file

@ -50,9 +50,6 @@ const (
// ReportSARIF set the output format to SARIF
ReportSARIF // SARIF format
//SonarqubeEffortMinutes effort to fix in minutes
SonarqubeEffortMinutes = 5
)
var text = `Results:
@ -132,51 +129,6 @@ func reportSonarqube(rootPaths []string, w io.Writer, data *reportInfo) error {
return err
}
func convertToSonarIssues(rootPaths []string, data *reportInfo) (*sonarIssues, error) {
si := &sonarIssues{[]sonarIssue{}}
for _, issue := range data.Issues {
var sonarFilePath string
for _, rootPath := range rootPaths {
if strings.HasPrefix(issue.File, rootPath) {
sonarFilePath = strings.Replace(issue.File, rootPath+"/", "", 1)
}
}
if sonarFilePath == "" {
continue
}
lines := strings.Split(issue.Line, "-")
startLine, err := strconv.Atoi(lines[0])
if err != nil {
return si, err
}
endLine := startLine
if len(lines) > 1 {
endLine, err = strconv.Atoi(lines[1])
if err != nil {
return si, err
}
}
s := sonarIssue{
EngineID: "gosec",
RuleID: issue.RuleID,
PrimaryLocation: location{
Message: issue.What,
FilePath: sonarFilePath,
TextRange: textRange{StartLine: startLine, EndLine: endLine},
},
Type: "VULNERABILITY",
Severity: getSonarSeverity(issue.Severity.String()),
EffortMinutes: SonarqubeEffortMinutes,
Cwe: issue.Cwe,
}
si.SonarIssues = append(si.SonarIssues, s)
}
return si, nil
}
func convertToSarifReport(rootPaths []string, data *reportInfo) (*sarifReport, error) {
sr := buildSarifReport()

View file

@ -9,6 +9,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/securego/gosec/v2"
"github.com/securego/gosec/v2/sonar"
"gopkg.in/yaml.v2"
)
@ -60,7 +61,7 @@ var _ = Describe("Formatter", func() {
data := &reportInfo{
Errors: map[string][]gosec.Error{},
Issues: []*gosec.Issue{
&gosec.Issue{
{
Severity: 2,
Confidence: 0,
RuleID: "test",
@ -77,15 +78,15 @@ var _ = Describe("Formatter", func() {
NumFound: 0,
},
}
want := &sonarIssues{
SonarIssues: []sonarIssue{
want := &sonar.Report{
Issues: []*sonar.Issue{
{
EngineID: "gosec",
RuleID: "test",
PrimaryLocation: location{
PrimaryLocation: &sonar.Location{
Message: "test",
FilePath: "test.go",
TextRange: textRange{
TextRange: &sonar.TextRange{
StartLine: 1,
EndLine: 2,
},
@ -108,7 +109,7 @@ var _ = Describe("Formatter", func() {
data := &reportInfo{
Errors: map[string][]gosec.Error{},
Issues: []*gosec.Issue{
&gosec.Issue{
{
Severity: 2,
Confidence: 0,
RuleID: "test",
@ -125,15 +126,15 @@ var _ = Describe("Formatter", func() {
NumFound: 0,
},
}
want := &sonarIssues{
SonarIssues: []sonarIssue{
want := &sonar.Report{
Issues: []*sonar.Issue{
{
EngineID: "gosec",
RuleID: "test",
PrimaryLocation: location{
PrimaryLocation: &sonar.Location{
Message: "test",
FilePath: "subfolder/test.go",
TextRange: textRange{
TextRange: &sonar.TextRange{
StartLine: 1,
EndLine: 2,
},
@ -155,7 +156,7 @@ var _ = Describe("Formatter", func() {
data := &reportInfo{
Errors: map[string][]gosec.Error{},
Issues: []*gosec.Issue{
&gosec.Issue{
{
Severity: 2,
Confidence: 0,
RuleID: "test",
@ -172,8 +173,8 @@ var _ = Describe("Formatter", func() {
NumFound: 0,
},
}
want := &sonarIssues{
SonarIssues: []sonarIssue{},
want := &sonar.Report{
Issues: []*sonar.Issue{},
}
rootPath := "/home/src/project2"
@ -187,7 +188,7 @@ var _ = Describe("Formatter", func() {
data := &reportInfo{
Errors: map[string][]gosec.Error{},
Issues: []*gosec.Issue{
&gosec.Issue{
{
Severity: 2,
Confidence: 0,
RuleID: "test",
@ -196,7 +197,7 @@ var _ = Describe("Formatter", func() {
Code: "",
Line: "1-2",
},
&gosec.Issue{
{
Severity: 2,
Confidence: 0,
RuleID: "test",
@ -213,15 +214,15 @@ var _ = Describe("Formatter", func() {
NumFound: 0,
},
}
want := &sonarIssues{
SonarIssues: []sonarIssue{
want := &sonar.Report{
Issues: []*sonar.Issue{
{
EngineID: "gosec",
RuleID: "test",
PrimaryLocation: location{
PrimaryLocation: &sonar.Location{
Message: "test",
FilePath: "test-project1.go",
TextRange: textRange{
TextRange: &sonar.TextRange{
StartLine: 1,
EndLine: 2,
},
@ -233,10 +234,10 @@ var _ = Describe("Formatter", func() {
{
EngineID: "gosec",
RuleID: "test",
PrimaryLocation: location{
PrimaryLocation: &sonar.Location{
Message: "test",
FilePath: "test-project2.go",
TextRange: textRange{
TextRange: &sonar.TextRange{
StartLine: 1,
EndLine: 2,
},
@ -407,7 +408,7 @@ var _ = Describe("Formatter", func() {
Expect(result).To(ContainSubstring(expectation))
}
})
It("sonarqube formatted report should contain the CWE mapping", func() {
It("sonarqube formatted report shouldn't contain the CWE mapping", func() {
for _, rule := range grules {
cwe := gosec.IssueToCWE[rule]
issue := createIssue(rule, cwe)
@ -424,7 +425,7 @@ var _ = Describe("Formatter", func() {
Expect(err).ShouldNot(HaveOccurred())
expectation := stripString(expect.String())
Expect(result).To(ContainSubstring(expectation))
Expect(result).ShouldNot(ContainSubstring(expectation))
}
})
It("golint formatted report should contain the CWE mapping", func() {

View file

@ -1,32 +1,79 @@
package output
import "github.com/securego/gosec/v2"
import (
"github.com/securego/gosec/v2"
"github.com/securego/gosec/v2/sonar"
"strconv"
"strings"
)
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"`
const (
//SonarqubeEffortMinutes effort to fix in minutes
SonarqubeEffortMinutes = 5
)
func convertToSonarIssues(rootPaths []string, data *reportInfo) (*sonar.Report, error) {
si := &sonar.Report{Issues: []*sonar.Issue{}}
for _, issue := range data.Issues {
sonarFilePath := parseFilePath(issue, rootPaths)
if sonarFilePath == "" {
continue
}
textRange, err := parseTextRange(issue)
if err != nil {
return si, err
}
primaryLocation := buildPrimaryLocation(issue.What, sonarFilePath, textRange)
severity := getSonarSeverity(issue.Severity.String())
s := &sonar.Issue{
EngineID: "gosec",
RuleID: issue.RuleID,
PrimaryLocation: primaryLocation,
Type: "VULNERABILITY",
Severity: severity,
EffortMinutes: SonarqubeEffortMinutes,
}
si.Issues = append(si.Issues, s)
}
return si, nil
}
type sonarIssue struct {
EngineID string `json:"engineId"`
RuleID string `json:"ruleId"`
Cwe gosec.Cwe `json:"cwe"`
PrimaryLocation location `json:"primaryLocation"`
Type string `json:"type"`
Severity string `json:"severity"`
EffortMinutes int `json:"effortMinutes"`
SecondaryLocations []location `json:"secondaryLocations,omitempty"`
func buildPrimaryLocation(message string, filePath string, textRange *sonar.TextRange) *sonar.Location {
return &sonar.Location{
Message: message,
FilePath: filePath,
TextRange: textRange,
}
}
type sonarIssues struct {
SonarIssues []sonarIssue `json:"issues"`
func parseFilePath(issue *gosec.Issue, rootPaths []string) string {
var sonarFilePath string
for _, rootPath := range rootPaths {
if strings.HasPrefix(issue.File, rootPath) {
sonarFilePath = strings.Replace(issue.File, rootPath+"/", "", 1)
}
}
return sonarFilePath
}
func parseTextRange(issue *gosec.Issue) (*sonar.TextRange, error) {
lines := strings.Split(issue.Line, "-")
startLine, err := strconv.Atoi(lines[0])
if err != nil {
return nil, err
}
endLine := startLine
if len(lines) > 1 {
endLine, err = strconv.Atoi(lines[1])
if err != nil {
return nil, err
}
}
return &sonar.TextRange{StartLine: startLine, EndLine: endLine}, nil
}
func getSonarSeverity(s string) string {

32
sonar/types.go Normal file
View file

@ -0,0 +1,32 @@
package sonar
//TextRange defines the text range of an issue's location
type TextRange struct {
StartLine int `json:"startLine"`
EndLine int `json:"endLine"`
StartColumn int `json:"startColumn,omitempty"`
EtartColumn int `json:"endColumn,omitempty"`
}
//Location defines a sonar issue's location
type Location struct {
Message string `json:"message"`
FilePath string `json:"filePath"`
TextRange *TextRange `json:"textRange,omitempty"`
}
//Issue defines a sonar issue
type Issue 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"`
}
//Report defines a sonar report
type Report struct {
Issues []*Issue `json:"issues"`
}