Skip to content

Commit

Permalink
Migrate sonar types in a dedicated package (#604)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmorel-35 committed May 5, 2021
1 parent b519743 commit 3763953
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 92 deletions.
48 changes: 0 additions & 48 deletions output/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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()

Expand Down
47 changes: 24 additions & 23 deletions output/formatter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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",
Expand All @@ -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,
},
Expand All @@ -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",
Expand All @@ -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,
},
Expand All @@ -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",
Expand All @@ -172,8 +173,8 @@ var _ = Describe("Formatter", func() {
NumFound: 0,
},
}
want := &sonarIssues{
SonarIssues: []sonarIssue{},
want := &sonar.Report{
Issues: []*sonar.Issue{},
}

rootPath := "/home/src/project2"
Expand All @@ -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",
Expand All @@ -196,7 +197,7 @@ var _ = Describe("Formatter", func() {
Code: "",
Line: "1-2",
},
&gosec.Issue{
{
Severity: 2,
Confidence: 0,
RuleID: "test",
Expand All @@ -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,
},
Expand All @@ -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,
},
Expand Down Expand Up @@ -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)
Expand All @@ -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() {
Expand Down
89 changes: 68 additions & 21 deletions output/sonarqube_format.go
Original file line number Diff line number Diff line change
@@ -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"`
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 location struct {
Message string `json:"message"`
FilePath string `json:"filePath"`
TextRange textRange `json:"textRange,omitempty"`

func buildPrimaryLocation(message string, filePath string, textRange *sonar.TextRange) *sonar.Location {
return &sonar.Location{
Message: message,
FilePath: filePath,
TextRange: textRange,
}
}

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 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
}

type sonarIssues struct {
SonarIssues []sonarIssue `json:"issues"`
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 {
Expand Down
32 changes: 32 additions & 0 deletions sonar/types.go
Original file line number Diff line number Diff line change
@@ -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"`
}

0 comments on commit 3763953

Please sign in to comment.