1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-09-16 09:26:22 +02:00

Add new unified fields to Mend and Blackduck SARIF (#4611)

* Add new unified fields to Mend and Blackduck SARIF

* fmt project

---------

Co-authored-by: Dmitrii Pavlukhin <dmitrii.pavlukhin@sap.com>
This commit is contained in:
Andrei Kireev
2023-10-17 11:48:52 +02:00
committed by GitHub
parent 3761a9f68a
commit 49f4c81344
7 changed files with 80 additions and 56 deletions

View File

@@ -524,13 +524,6 @@ func checkPolicyViolations(ctx context.Context, config *ScanOptions, scan *ws.Sc
return piperutils.Path{}, fmt.Errorf("failed to retrieve project policy alerts from WhiteSource: %w", err)
}
// TODO add ignored alerts to list of all alerts
_, err = sys.GetProjectIgnoredAlertsByType(project.Token, "REJECTED_BY_POLICY_RESOURCE")
if err != nil {
return piperutils.Path{}, fmt.Errorf("failed to retrieve project policy ignored alerts from WhiteSource: %w", err)
}
// alerts = append(alerts, ignoredAlerts...)
policyViolationCount += len(alerts)
allAlerts = append(allAlerts, alerts...)
}
@@ -766,7 +759,11 @@ func reportGitHubIssuesAndCreateReports(
reportPaths = append(reportPaths, paths...)
sarif := ws.CreateSarifResultFile(scan, &allAlerts)
combinedAlerts := make([]ws.Alert, 0, len(allAlerts)+len(allAssessedAlerts))
combinedAlerts = append(combinedAlerts, allAlerts...)
combinedAlerts = append(combinedAlerts, allAssessedAlerts...)
sarif := ws.CreateSarifResultFile(scan, &combinedAlerts)
paths, err = ws.WriteSarifFile(sarif, utils)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
@@ -816,18 +813,15 @@ func readAssessmentsFromFile(assessmentFilePath string, utils whitesourceUtils)
// checkSecurityViolations checks security violations and returns an error if the configured severity limit is crossed. Besides the potential error the list of unassessed and assessed alerts are being returned to allow generating reports and issues from the data.
func checkProjectSecurityViolations(config *ScanOptions, cvssSeverityLimit float64, project ws.Project, sys whitesource, assessments *[]format.Assessment, influx *whitesourceExecuteScanInflux) (int, []ws.Alert, []ws.Alert, error) {
// get project alerts (vulnerabilities)
assessedAlerts := []ws.Alert{}
alerts, err := sys.GetProjectAlertsByType(project.Token, "SECURITY_VULNERABILITY")
if err != nil {
return 0, alerts, assessedAlerts, fmt.Errorf("failed to retrieve project alerts from WhiteSource: %w", err)
return 0, alerts, []ws.Alert{}, fmt.Errorf("failed to retrieve project alerts from WhiteSource: %w", err)
}
// TODO add ignored alerts to list of all alerts
_, err = sys.GetProjectIgnoredAlertsByType(project.Token, "SECURITY_VULNERABILITY")
assessedAlerts, err := sys.GetProjectIgnoredAlertsByType(project.Token, "SECURITY_VULNERABILITY")
if err != nil {
return 0, alerts, assessedAlerts, fmt.Errorf("failed to retrieve project ignored alerts from WhiteSource: %w", err)
return 0, alerts, []ws.Alert{}, fmt.Errorf("failed to retrieve project ignored alerts from WhiteSource: %w", err)
}
// alerts = append(alerts, ignoredAlerts...)
// filter alerts related to existing assessments
filteredAlerts := []ws.Alert{}
@@ -915,13 +909,6 @@ func aggregateVersionWideVulnerabilities(config *ScanOptions, utils whitesourceU
return errors.Wrapf(err, "failed to get project alerts by type")
}
// TODO add ignored alerts to list of all alerts
_, err = sys.GetProjectIgnoredAlertsByType(project.Token, "SECURITY_VULNERABILITY")
if err != nil {
return errors.Wrapf(err, "failed to get project ignored alerts by type")
}
// alerts = append(alerts, ignoredAlerts...)
log.Entry().Infof("Found project: %s with %v vulnerabilities.", project.Name, len(alerts))
versionWideAlerts = append(versionWideAlerts, alerts...)
}

View File

@@ -143,6 +143,7 @@ type VulnerabilityWithRemediation struct {
ExploitabilitySubscore float32 `json:"exploitabilitySubscore,omitempty"`
ImpactSubscore float32 `json:"impactSubscore,omitempty"`
RelatedVulnerability string `json:"relatedVulnerability,omitempty"`
RemidiatedBy string `json:"remediationCreatedBy,omitempty"`
}
// Title returns the issue title representation of the contents

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"path/filepath"
"runtime"
"strings"
"github.com/SAP/jenkins-library/pkg/format"
"github.com/SAP/jenkins-library/pkg/log"
@@ -70,12 +71,17 @@ func CreateSarifResultFile(vulns *Vulnerabilities, projectName, projectVersion,
PackageURLPlusCVEHash: base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v+%v", v.Component.ToPackageUrl().ToString(), v.CweID))),
},
Properties: &format.SarifProperties{
Audited: isAudited,
ToolSeverity: v.Severity,
ToolSeverityIndex: severityIndex[v.Severity],
ToolAuditMessage: v.VulnerabilityWithRemediation.RemediationComment,
ToolState: v.RemediationStatus,
UnifiedAuditState: unifiedStatusValue,
Audited: isAudited,
ToolSeverity: v.Severity,
ToolSeverityIndex: severityIndex[v.Severity],
ToolState: v.RemediationStatus,
ToolAuditMessage: v.VulnerabilityWithRemediation.RemediationComment,
UnifiedAuditState: unifiedStatusValue,
UnifiedSeverity: strings.ToLower(v.Severity),
UnifiedCriticality: v.BaseScore,
UnifiedAuditUser: v.VulnerabilityWithRemediation.RemidiatedBy,
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
},
}

View File

@@ -32,6 +32,7 @@ func TestCreateSarifResultFile(t *testing.T) {
BaseScore: 9.8, OverallScore: 10,
RemediationStatus: "IGNORED",
RemediationComment: "CWE-45456543 Auto-remediated: CWE-45456543 is related to CVE-1, but the CWE team has determined that this component version is not affected.",
RemidiatedBy: "technical_user",
},
},
{
@@ -60,6 +61,7 @@ func TestCreateSarifResultFile(t *testing.T) {
Description: "Some vulnerability that can be exploited by turning it upside down.",
BaseScore: 6.5,
OverallScore: 7,
RemediationStatus: "IGNORED",
},
},
{
@@ -110,6 +112,13 @@ func TestCreateSarifResultFile(t *testing.T) {
// Test correctness of audit information
assert.Equal(t, true, sarif.Runs[0].Results[0].Properties.Audited)
assert.Equal(t, "IGNORED", sarif.Runs[0].Results[0].Properties.ToolState)
assert.Equal(t, alerts[0].BaseScore, sarif.Runs[0].Results[0].Properties.UnifiedCriticality)
assert.Equal(t, "critical", sarif.Runs[0].Results[0].Properties.UnifiedSeverity)
assert.Equal(t, "new", sarif.Runs[0].Results[1].Properties.UnifiedAuditState)
assert.Equal(t, "notRelevant", sarif.Runs[0].Results[0].Properties.UnifiedAuditState)
assert.Equal(t, "technical_user", sarif.Runs[0].Results[0].Properties.UnifiedAuditUser)
assert.Equal(t, format.AUDIT_REQUIREMENT_GROUP_1_DESC, sarif.Runs[0].Results[0].Properties.AuditRequirement)
assert.Equal(t, format.AUDIT_REQUIREMENT_GROUP_1_INDEX, sarif.Runs[0].Results[0].Properties.AuditRequirementIndex)
assert.Equal(t,
"CWE-45456543 Auto-remediated: CWE-45456543 is related to CVE-1, but the CWE team has determined that this component version is not affected.",
sarif.Runs[0].Results[0].Properties.ToolAuditMessage,

View File

@@ -96,17 +96,20 @@ type PartialFingerprints struct {
// SarifProperties adding additional information/context to the finding
type SarifProperties struct {
// common
RuleGUID string `json:"ruleGUID,omitempty"`
InstanceID string `json:"instanceID,omitempty"`
Audited bool `json:"audited"`
ToolSeverity string `json:"toolSeverity"`
ToolSeverityIndex int `json:"toolSeverityIndex"`
ToolState string `json:"toolState"`
ToolStateIndex int `json:"toolStateIndex"`
ToolAuditMessage string `json:"toolAuditMessage"`
UnifiedAuditState string `json:"unifiedAuditState"`
AuditRequirement string `json:"auditRequirement"`
AuditRequirementIndex int `json:"auditRequirementIndex"`
RuleGUID string `json:"ruleGUID,omitempty"`
InstanceID string `json:"instanceID,omitempty"`
Audited bool `json:"audited"`
ToolSeverity string `json:"toolSeverity"`
ToolSeverityIndex int `json:"toolSeverityIndex"`
ToolState string `json:"toolState"`
ToolStateIndex int `json:"toolStateIndex"`
ToolAuditMessage string `json:"toolAuditMessage"`
UnifiedAuditState string `json:"unifiedAuditState,omitempty"`
UnifiedSeverity string `json:"unifiedSeverity,omitempty"`
UnifiedCriticality float32 `json:"unifiedCriticality,omitempty"`
UnifiedAuditUser string `json:"unifiedAuditUser,omitempty"`
AuditRequirement string `json:"auditRequirement"`
AuditRequirementIndex int `json:"auditRequirementIndex"`
// specific
InstanceSeverity string `json:"instanceSeverity"`

View File

@@ -40,7 +40,7 @@ func CreateCustomVulnerabilityReport(productName string, scan *Scan, alerts *[]A
{Description: "Filtered project names", Details: strings.Join(projectNames, ", ")},
},
Overview: []reporting.OverviewRow{
{Description: "Total number of vulnerabilities", Details: fmt.Sprint(len((*alerts)))},
{Description: "Total number of vulnerabilities", Details: fmt.Sprint(len(*alerts))},
{Description: "Total number of high/critical vulnerabilities with CVSS score >= 7.0", Details: fmt.Sprint(severe)},
},
SuccessfulScan: severe == 0,
@@ -295,9 +295,13 @@ func getAuditInformation(alert Alert) *format.SarifProperties {
}
return &format.SarifProperties{
Audited: isAudited,
ToolAuditMessage: auditMessage,
UnifiedAuditState: unifiedAuditState,
Audited: isAudited,
ToolAuditMessage: auditMessage,
UnifiedAuditState: unifiedAuditState,
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
UnifiedSeverity: alert.Vulnerability.CVSS3Severity,
UnifiedCriticality: float32(alert.Vulnerability.CVSS3Score),
}
}

View File

@@ -349,9 +349,11 @@ func TestGetAuditInformation(t *testing.T) {
Status: "OPEN",
},
expected: &format.SarifProperties{
Audited: false,
ToolAuditMessage: "",
UnifiedAuditState: "new",
Audited: false,
ToolAuditMessage: "",
UnifiedAuditState: "new",
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
},
},
{
@@ -359,11 +361,19 @@ func TestGetAuditInformation(t *testing.T) {
alert: Alert{
Status: "IGNORE",
Comments: "Not relevant alert",
Vulnerability: Vulnerability{
CVSS3Score: 9.3,
CVSS3Severity: "critical",
},
},
expected: &format.SarifProperties{
Audited: true,
ToolAuditMessage: "Not relevant alert",
UnifiedAuditState: "notRelevant",
Audited: true,
ToolAuditMessage: "Not relevant alert",
UnifiedAuditState: "notRelevant",
UnifiedSeverity: "critical",
UnifiedCriticality: 9.3,
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
},
},
{
@@ -373,13 +383,15 @@ func TestGetAuditInformation(t *testing.T) {
Comments: "Some comment",
},
expected: &format.SarifProperties{
Audited: false,
ToolAuditMessage: "",
UnifiedAuditState: "new",
Audited: false,
ToolAuditMessage: "",
UnifiedAuditState: "new",
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
},
},
{
name: "Audited alert",
name: "Not audited alert",
alert: Alert{
Assessment: &format.Assessment{
Status: format.NotRelevant,
@@ -389,16 +401,18 @@ func TestGetAuditInformation(t *testing.T) {
Comments: "New alert",
},
expected: &format.SarifProperties{
Audited: true,
ToolAuditMessage: string(format.FixedByDevTeam),
UnifiedAuditState: "notRelevant",
Audited: true,
ToolAuditMessage: string(format.FixedByDevTeam),
UnifiedAuditState: "notRelevant",
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
},
},
}
for _, test := range tt {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, getAuditInformation(test.alert), test.expected)
assert.Equal(t, test.expected, getAuditInformation(test.alert))
})
}
}