mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-03-03 15:02:35 +02:00
feat(checkmarxExecuteScan): Improve cx report (#2991)
* Improve checkmarx report * Fix test and fmt Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
parent
d3e2086410
commit
86e8125279
@ -304,18 +304,26 @@ func verifyCxProjectCompliance(config checkmarxExecuteScanOptions, sys checkmarx
|
||||
reports = append(reports, piperutils.Path{Target: toolRecordFileName})
|
||||
}
|
||||
|
||||
scanReport := checkmarx.CreateCustomReport(results)
|
||||
paths, err := checkmarx.WriteCustomReports(scanReport, fmt.Sprint(results["ProjectName"]), fmt.Sprint(results["ProjectID"]))
|
||||
reports = append(reports, paths...)
|
||||
|
||||
links := []piperutils.Path{{Target: results["DeepLink"].(string), Name: "Checkmarx Web UI"}}
|
||||
piperutils.PersistReportsAndLinks("checkmarxExecuteScan", utils.GetWorkspace(), reports, links)
|
||||
|
||||
reportToInflux(results, influx)
|
||||
|
||||
insecure := false
|
||||
insecureResults := []string{}
|
||||
neutralResults := []string{}
|
||||
|
||||
err = nil
|
||||
if config.VulnerabilityThresholdEnabled {
|
||||
insecure = enforceThresholds(config, results)
|
||||
insecure, insecureResults, neutralResults = enforceThresholds(config, results)
|
||||
scanReport := checkmarx.CreateCustomReport(results, insecureResults, neutralResults)
|
||||
paths, err := checkmarx.WriteCustomReports(scanReport, fmt.Sprint(results["ProjectName"]), fmt.Sprint(results["ProjectID"]))
|
||||
if err != nil {
|
||||
// do not fail until we have a better idea to handle it
|
||||
log.Entry().Warning("failed to write HTML/MarkDown report file ...", err)
|
||||
} else {
|
||||
reports = append(reports, paths...)
|
||||
}
|
||||
}
|
||||
|
||||
if insecure {
|
||||
@ -429,7 +437,9 @@ func downloadAndSaveReport(sys checkmarx.System, reportFileName string, scanID i
|
||||
return utils.WriteFile(reportFileName, report, 0700)
|
||||
}
|
||||
|
||||
func enforceThresholds(config checkmarxExecuteScanOptions, results map[string]interface{}) bool {
|
||||
func enforceThresholds(config checkmarxExecuteScanOptions, results map[string]interface{}) (bool, []string, []string) {
|
||||
neutralResults := []string{}
|
||||
insecureResults := []string{}
|
||||
insecure := false
|
||||
cxHighThreshold := config.VulnerabilityThresholdHigh
|
||||
cxMediumThreshold := config.VulnerabilityThresholdMedium
|
||||
@ -494,13 +504,32 @@ func enforceThresholds(config checkmarxExecuteScanOptions, results map[string]in
|
||||
}
|
||||
}
|
||||
|
||||
highText := fmt.Sprintf("High %v%v %v", highValue, unit, highViolation)
|
||||
mediumText := fmt.Sprintf("Medium %v%v %v", mediumValue, unit, mediumViolation)
|
||||
lowText := fmt.Sprintf("Low %v%v %v", lowValue, unit, lowViolation)
|
||||
if len(highViolation) > 0 {
|
||||
insecureResults = append(insecureResults, highText)
|
||||
} else {
|
||||
neutralResults = append(neutralResults, highText)
|
||||
}
|
||||
if len(mediumViolation) > 0 {
|
||||
insecureResults = append(insecureResults, mediumText)
|
||||
} else {
|
||||
neutralResults = append(neutralResults, mediumText)
|
||||
}
|
||||
if len(lowViolation) > 0 {
|
||||
insecureResults = append(insecureResults, lowText)
|
||||
} else {
|
||||
neutralResults = append(neutralResults, lowText)
|
||||
}
|
||||
|
||||
log.Entry().Infoln("")
|
||||
log.Entry().Infof("High %v%v %v", highValue, unit, highViolation)
|
||||
log.Entry().Infof("Medium %v%v %v", mediumValue, unit, mediumViolation)
|
||||
log.Entry().Infof("Low %v%v %v", lowValue, unit, lowViolation)
|
||||
log.Entry().Info(highText)
|
||||
log.Entry().Info(mediumText)
|
||||
log.Entry().Info(lowText)
|
||||
log.Entry().Infoln("")
|
||||
|
||||
return insecure
|
||||
return insecure, insecureResults, neutralResults
|
||||
}
|
||||
|
||||
func createAndConfigureNewProject(sys checkmarx.System, projectName, teamID string, presetIDValue int, presetValue, engineConfiguration string) (checkmarx.Project, error) {
|
||||
|
@ -899,72 +899,88 @@ func TestEnforceThresholds(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 100, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("absolute high violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdHigh: 5, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("percentage medium violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdMedium: 100, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("absolute medium violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdMedium: 5, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("percentage low violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdLow: 100, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("absolute low violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdLow: 5, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("percentage no violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdLow: 0, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, false, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 0, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 3, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
|
||||
t.Run("absolute no violation", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdLow: 15, VulnerabilityThresholdMedium: 15, VulnerabilityThresholdHigh: 15, VulnerabilityThresholdEnabled: true}
|
||||
insecure := enforceThresholds(options, results)
|
||||
insecure, insecureResults, neutralResults := enforceThresholds(options, results)
|
||||
|
||||
assert.Equal(t, false, insecure, "Expected results to be insecure but where not")
|
||||
assert.Equal(t, 0, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
|
||||
assert.Equal(t, 3, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,9 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func CreateCustomReport(data map[string]interface{}) reporting.ScanReport {
|
||||
func CreateCustomReport(data map[string]interface{}, insecure, neutral []string) reporting.ScanReport {
|
||||
deepLink := fmt.Sprintf(`<a href="%v" target="_blank">Link to scan in CX UI</a>`, data["DeepLink"])
|
||||
|
||||
scanReport := reporting.ScanReport{
|
||||
Title: "Checkmarx SAST Report",
|
||||
Subheaders: []reporting.Subheader{
|
||||
@ -32,41 +34,72 @@ func CreateCustomReport(data map[string]interface{}) reporting.ScanReport {
|
||||
{Description: "Lines of code scanned", Details: fmt.Sprint(data["LinesOfCodeScanned)"])},
|
||||
{Description: "Files scanned", Details: fmt.Sprint(data["FilesScanned)"])},
|
||||
{Description: "Checkmarx version", Details: fmt.Sprint(data["CheckmarxVersion"])},
|
||||
{Description: "Deep link", Details: fmt.Sprint(data["DeepLink"])},
|
||||
},
|
||||
Overview: []reporting.OverviewRow{
|
||||
{Description: "High issues", Details: fmt.Sprint(data["High"].(map[string]int)["Issues"])},
|
||||
{Description: "High not false positive issues", Details: fmt.Sprint(data["High"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "High not exploitable issues", Details: fmt.Sprint(data["High"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "High confirmed issues", Details: fmt.Sprint(data["High"].(map[string]int)["Confirmed"])},
|
||||
{Description: "High urgent issues", Details: fmt.Sprint(data["High"].(map[string]int)["Urgent"])},
|
||||
{Description: "High proposed not exploitable issues", Details: fmt.Sprint(data["High"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "High to verify issues", Details: fmt.Sprint(data["High"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Medium issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["Issues"])},
|
||||
{Description: "Medium not false positive issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "Medium not exploitable issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "Medium confirmed issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["Confirmed"])},
|
||||
{Description: "Medium urgent issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["Urgent"])},
|
||||
{Description: "Medium proposed not exploitable issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "Medium to verify issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Low issues", Details: fmt.Sprint(data["Low"].(map[string]int)["Issues"])},
|
||||
{Description: "Low not false positive issues", Details: fmt.Sprint(data["Low"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "Low not exploitable issues", Details: fmt.Sprint(data["Low"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "Low confirmed issues", Details: fmt.Sprint(data["Low"].(map[string]int)["Confirmed"])},
|
||||
{Description: "Low urgent issues", Details: fmt.Sprint(data["Low"].(map[string]int)["Urgent"])},
|
||||
{Description: "Low proposed not exploitable issues", Details: fmt.Sprint(data["Low"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "Low to verify issues", Details: fmt.Sprint(data["Low"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Informational issues", Details: fmt.Sprint(data["Information"].(map[string]int)["Issues"])},
|
||||
{Description: "Informational not false positive issues", Details: fmt.Sprint(data["Information"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "Informational not exploitable issues", Details: fmt.Sprint(data["Information"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "Informational confirmed issues", Details: fmt.Sprint(data["Information"].(map[string]int)["Confirmed"])},
|
||||
{Description: "Informational urgent issues", Details: fmt.Sprint(data["Information"].(map[string]int)["Urgent"])},
|
||||
{Description: "Informational proposed not exploitable issues", Details: fmt.Sprint(data["Information"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "Informational to verify issues", Details: fmt.Sprint(data["Information"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Deep link", Details: deepLink},
|
||||
},
|
||||
Overview: []reporting.OverviewRow{},
|
||||
ReportTime: time.Now(),
|
||||
}
|
||||
|
||||
for _, issue := range insecure {
|
||||
row := reporting.OverviewRow{}
|
||||
row.Description = fmt.Sprint(issue)
|
||||
row.Style = reporting.Red
|
||||
|
||||
scanReport.Overview = append(scanReport.Overview, row)
|
||||
}
|
||||
for _, issue := range neutral {
|
||||
row := reporting.OverviewRow{}
|
||||
row.Description = fmt.Sprint(issue)
|
||||
|
||||
scanReport.Overview = append(scanReport.Overview, row)
|
||||
}
|
||||
|
||||
detailTable := reporting.ScanDetailTable{
|
||||
Headers: []string{
|
||||
"KPI",
|
||||
"Count",
|
||||
},
|
||||
WithCounter: false,
|
||||
}
|
||||
detailRows := []reporting.OverviewRow{
|
||||
{Description: "High issues", Details: fmt.Sprint(data["High"].(map[string]int)["Issues"])},
|
||||
{Description: "High not false positive issues", Details: fmt.Sprint(data["High"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "High not exploitable issues", Details: fmt.Sprint(data["High"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "High confirmed issues", Details: fmt.Sprint(data["High"].(map[string]int)["Confirmed"])},
|
||||
{Description: "High urgent issues", Details: fmt.Sprint(data["High"].(map[string]int)["Urgent"])},
|
||||
{Description: "High proposed not exploitable issues", Details: fmt.Sprint(data["High"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "High to verify issues", Details: fmt.Sprint(data["High"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Medium issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["Issues"])},
|
||||
{Description: "Medium not false positive issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "Medium not exploitable issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "Medium confirmed issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["Confirmed"])},
|
||||
{Description: "Medium urgent issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["Urgent"])},
|
||||
{Description: "Medium proposed not exploitable issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "Medium to verify issues", Details: fmt.Sprint(data["Medium"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Low issues", Details: fmt.Sprint(data["Low"].(map[string]int)["Issues"])},
|
||||
{Description: "Low not false positive issues", Details: fmt.Sprint(data["Low"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "Low not exploitable issues", Details: fmt.Sprint(data["Low"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "Low confirmed issues", Details: fmt.Sprint(data["Low"].(map[string]int)["Confirmed"])},
|
||||
{Description: "Low urgent issues", Details: fmt.Sprint(data["Low"].(map[string]int)["Urgent"])},
|
||||
{Description: "Low proposed not exploitable issues", Details: fmt.Sprint(data["Low"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "Low to verify issues", Details: fmt.Sprint(data["Low"].(map[string]int)["ToVerify"])},
|
||||
{Description: "Informational issues", Details: fmt.Sprint(data["Information"].(map[string]int)["Issues"])},
|
||||
{Description: "Informational not false positive issues", Details: fmt.Sprint(data["Information"].(map[string]int)["NotFalsePositive"])},
|
||||
{Description: "Informational not exploitable issues", Details: fmt.Sprint(data["Information"].(map[string]int)["NotExploitable"])},
|
||||
{Description: "Informational confirmed issues", Details: fmt.Sprint(data["Information"].(map[string]int)["Confirmed"])},
|
||||
{Description: "Informational urgent issues", Details: fmt.Sprint(data["Information"].(map[string]int)["Urgent"])},
|
||||
{Description: "Informational proposed not exploitable issues", Details: fmt.Sprint(data["Information"].(map[string]int)["ProposedNotExploitable"])},
|
||||
{Description: "Informational to verify issues", Details: fmt.Sprint(data["Information"].(map[string]int)["ToVerify"])},
|
||||
}
|
||||
for _, detailRow := range detailRows {
|
||||
row := reporting.ScanRow{}
|
||||
row.AddColumn(detailRow.Description, 0)
|
||||
row.AddColumn(detailRow.Details, 0)
|
||||
|
||||
detailTable.Rows = append(detailTable.Rows, row)
|
||||
}
|
||||
scanReport.DetailTable = detailTable
|
||||
|
||||
return scanReport
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user