Skip to content

Commit 49f4c81

Browse files
Add new unified fields to Mend and Blackduck SARIF (SAP#4611)
* Add new unified fields to Mend and Blackduck SARIF * fmt project --------- Co-authored-by: Dmitrii Pavlukhin <[email protected]>
1 parent 3761a9f commit 49f4c81

File tree

7 files changed

+80
-56
lines changed

7 files changed

+80
-56
lines changed

cmd/whitesourceExecuteScan.go

+8-21
Original file line numberDiff line numberDiff line change
@@ -524,13 +524,6 @@ func checkPolicyViolations(ctx context.Context, config *ScanOptions, scan *ws.Sc
524524
return piperutils.Path{}, fmt.Errorf("failed to retrieve project policy alerts from WhiteSource: %w", err)
525525
}
526526

527-
// TODO add ignored alerts to list of all alerts
528-
_, err = sys.GetProjectIgnoredAlertsByType(project.Token, "REJECTED_BY_POLICY_RESOURCE")
529-
if err != nil {
530-
return piperutils.Path{}, fmt.Errorf("failed to retrieve project policy ignored alerts from WhiteSource: %w", err)
531-
}
532-
// alerts = append(alerts, ignoredAlerts...)
533-
534527
policyViolationCount += len(alerts)
535528
allAlerts = append(allAlerts, alerts...)
536529
}
@@ -766,7 +759,11 @@ func reportGitHubIssuesAndCreateReports(
766759

767760
reportPaths = append(reportPaths, paths...)
768761

769-
sarif := ws.CreateSarifResultFile(scan, &allAlerts)
762+
combinedAlerts := make([]ws.Alert, 0, len(allAlerts)+len(allAssessedAlerts))
763+
combinedAlerts = append(combinedAlerts, allAlerts...)
764+
combinedAlerts = append(combinedAlerts, allAssessedAlerts...)
765+
766+
sarif := ws.CreateSarifResultFile(scan, &combinedAlerts)
770767
paths, err = ws.WriteSarifFile(sarif, utils)
771768
if err != nil {
772769
errorsOccured = append(errorsOccured, fmt.Sprint(err))
@@ -816,18 +813,15 @@ func readAssessmentsFromFile(assessmentFilePath string, utils whitesourceUtils)
816813
// 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.
817814
func checkProjectSecurityViolations(config *ScanOptions, cvssSeverityLimit float64, project ws.Project, sys whitesource, assessments *[]format.Assessment, influx *whitesourceExecuteScanInflux) (int, []ws.Alert, []ws.Alert, error) {
818815
// get project alerts (vulnerabilities)
819-
assessedAlerts := []ws.Alert{}
820816
alerts, err := sys.GetProjectAlertsByType(project.Token, "SECURITY_VULNERABILITY")
821817
if err != nil {
822-
return 0, alerts, assessedAlerts, fmt.Errorf("failed to retrieve project alerts from WhiteSource: %w", err)
818+
return 0, alerts, []ws.Alert{}, fmt.Errorf("failed to retrieve project alerts from WhiteSource: %w", err)
823819
}
824820

825-
// TODO add ignored alerts to list of all alerts
826-
_, err = sys.GetProjectIgnoredAlertsByType(project.Token, "SECURITY_VULNERABILITY")
821+
assessedAlerts, err := sys.GetProjectIgnoredAlertsByType(project.Token, "SECURITY_VULNERABILITY")
827822
if err != nil {
828-
return 0, alerts, assessedAlerts, fmt.Errorf("failed to retrieve project ignored alerts from WhiteSource: %w", err)
823+
return 0, alerts, []ws.Alert{}, fmt.Errorf("failed to retrieve project ignored alerts from WhiteSource: %w", err)
829824
}
830-
// alerts = append(alerts, ignoredAlerts...)
831825

832826
// filter alerts related to existing assessments
833827
filteredAlerts := []ws.Alert{}
@@ -915,13 +909,6 @@ func aggregateVersionWideVulnerabilities(config *ScanOptions, utils whitesourceU
915909
return errors.Wrapf(err, "failed to get project alerts by type")
916910
}
917911

918-
// TODO add ignored alerts to list of all alerts
919-
_, err = sys.GetProjectIgnoredAlertsByType(project.Token, "SECURITY_VULNERABILITY")
920-
if err != nil {
921-
return errors.Wrapf(err, "failed to get project ignored alerts by type")
922-
}
923-
// alerts = append(alerts, ignoredAlerts...)
924-
925912
log.Entry().Infof("Found project: %s with %v vulnerabilities.", project.Name, len(alerts))
926913
versionWideAlerts = append(versionWideAlerts, alerts...)
927914
}

pkg/blackduck/blackduck.go

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ type VulnerabilityWithRemediation struct {
143143
ExploitabilitySubscore float32 `json:"exploitabilitySubscore,omitempty"`
144144
ImpactSubscore float32 `json:"impactSubscore,omitempty"`
145145
RelatedVulnerability string `json:"relatedVulnerability,omitempty"`
146+
RemidiatedBy string `json:"remediationCreatedBy,omitempty"`
146147
}
147148

148149
// Title returns the issue title representation of the contents

pkg/blackduck/reporting.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"path/filepath"
88
"runtime"
9+
"strings"
910

1011
"github.com/SAP/jenkins-library/pkg/format"
1112
"github.com/SAP/jenkins-library/pkg/log"
@@ -70,12 +71,17 @@ func CreateSarifResultFile(vulns *Vulnerabilities, projectName, projectVersion,
7071
PackageURLPlusCVEHash: base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%v+%v", v.Component.ToPackageUrl().ToString(), v.CweID))),
7172
},
7273
Properties: &format.SarifProperties{
73-
Audited: isAudited,
74-
ToolSeverity: v.Severity,
75-
ToolSeverityIndex: severityIndex[v.Severity],
76-
ToolAuditMessage: v.VulnerabilityWithRemediation.RemediationComment,
77-
ToolState: v.RemediationStatus,
78-
UnifiedAuditState: unifiedStatusValue,
74+
Audited: isAudited,
75+
ToolSeverity: v.Severity,
76+
ToolSeverityIndex: severityIndex[v.Severity],
77+
ToolState: v.RemediationStatus,
78+
ToolAuditMessage: v.VulnerabilityWithRemediation.RemediationComment,
79+
UnifiedAuditState: unifiedStatusValue,
80+
UnifiedSeverity: strings.ToLower(v.Severity),
81+
UnifiedCriticality: v.BaseScore,
82+
UnifiedAuditUser: v.VulnerabilityWithRemediation.RemidiatedBy,
83+
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
84+
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
7985
},
8086
}
8187

pkg/blackduck/reporting_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func TestCreateSarifResultFile(t *testing.T) {
3232
BaseScore: 9.8, OverallScore: 10,
3333
RemediationStatus: "IGNORED",
3434
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.",
35+
RemidiatedBy: "technical_user",
3536
},
3637
},
3738
{
@@ -60,6 +61,7 @@ func TestCreateSarifResultFile(t *testing.T) {
6061
Description: "Some vulnerability that can be exploited by turning it upside down.",
6162
BaseScore: 6.5,
6263
OverallScore: 7,
64+
RemediationStatus: "IGNORED",
6365
},
6466
},
6567
{
@@ -110,6 +112,13 @@ func TestCreateSarifResultFile(t *testing.T) {
110112
// Test correctness of audit information
111113
assert.Equal(t, true, sarif.Runs[0].Results[0].Properties.Audited)
112114
assert.Equal(t, "IGNORED", sarif.Runs[0].Results[0].Properties.ToolState)
115+
assert.Equal(t, alerts[0].BaseScore, sarif.Runs[0].Results[0].Properties.UnifiedCriticality)
116+
assert.Equal(t, "critical", sarif.Runs[0].Results[0].Properties.UnifiedSeverity)
117+
assert.Equal(t, "new", sarif.Runs[0].Results[1].Properties.UnifiedAuditState)
118+
assert.Equal(t, "notRelevant", sarif.Runs[0].Results[0].Properties.UnifiedAuditState)
119+
assert.Equal(t, "technical_user", sarif.Runs[0].Results[0].Properties.UnifiedAuditUser)
120+
assert.Equal(t, format.AUDIT_REQUIREMENT_GROUP_1_DESC, sarif.Runs[0].Results[0].Properties.AuditRequirement)
121+
assert.Equal(t, format.AUDIT_REQUIREMENT_GROUP_1_INDEX, sarif.Runs[0].Results[0].Properties.AuditRequirementIndex)
113122
assert.Equal(t,
114123
"CWE-45456543 Auto-remediated: CWE-45456543 is related to CVE-1, but the CWE team has determined that this component version is not affected.",
115124
sarif.Runs[0].Results[0].Properties.ToolAuditMessage,

pkg/format/sarif.go

+14-11
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,20 @@ type PartialFingerprints struct {
9696
// SarifProperties adding additional information/context to the finding
9797
type SarifProperties struct {
9898
// common
99-
RuleGUID string `json:"ruleGUID,omitempty"`
100-
InstanceID string `json:"instanceID,omitempty"`
101-
Audited bool `json:"audited"`
102-
ToolSeverity string `json:"toolSeverity"`
103-
ToolSeverityIndex int `json:"toolSeverityIndex"`
104-
ToolState string `json:"toolState"`
105-
ToolStateIndex int `json:"toolStateIndex"`
106-
ToolAuditMessage string `json:"toolAuditMessage"`
107-
UnifiedAuditState string `json:"unifiedAuditState"`
108-
AuditRequirement string `json:"auditRequirement"`
109-
AuditRequirementIndex int `json:"auditRequirementIndex"`
99+
RuleGUID string `json:"ruleGUID,omitempty"`
100+
InstanceID string `json:"instanceID,omitempty"`
101+
Audited bool `json:"audited"`
102+
ToolSeverity string `json:"toolSeverity"`
103+
ToolSeverityIndex int `json:"toolSeverityIndex"`
104+
ToolState string `json:"toolState"`
105+
ToolStateIndex int `json:"toolStateIndex"`
106+
ToolAuditMessage string `json:"toolAuditMessage"`
107+
UnifiedAuditState string `json:"unifiedAuditState,omitempty"`
108+
UnifiedSeverity string `json:"unifiedSeverity,omitempty"`
109+
UnifiedCriticality float32 `json:"unifiedCriticality,omitempty"`
110+
UnifiedAuditUser string `json:"unifiedAuditUser,omitempty"`
111+
AuditRequirement string `json:"auditRequirement"`
112+
AuditRequirementIndex int `json:"auditRequirementIndex"`
110113

111114
// specific
112115
InstanceSeverity string `json:"instanceSeverity"`

pkg/whitesource/reporting.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func CreateCustomVulnerabilityReport(productName string, scan *Scan, alerts *[]A
4040
{Description: "Filtered project names", Details: strings.Join(projectNames, ", ")},
4141
},
4242
Overview: []reporting.OverviewRow{
43-
{Description: "Total number of vulnerabilities", Details: fmt.Sprint(len((*alerts)))},
43+
{Description: "Total number of vulnerabilities", Details: fmt.Sprint(len(*alerts))},
4444
{Description: "Total number of high/critical vulnerabilities with CVSS score >= 7.0", Details: fmt.Sprint(severe)},
4545
},
4646
SuccessfulScan: severe == 0,
@@ -295,9 +295,13 @@ func getAuditInformation(alert Alert) *format.SarifProperties {
295295
}
296296

297297
return &format.SarifProperties{
298-
Audited: isAudited,
299-
ToolAuditMessage: auditMessage,
300-
UnifiedAuditState: unifiedAuditState,
298+
Audited: isAudited,
299+
ToolAuditMessage: auditMessage,
300+
UnifiedAuditState: unifiedAuditState,
301+
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
302+
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
303+
UnifiedSeverity: alert.Vulnerability.CVSS3Severity,
304+
UnifiedCriticality: float32(alert.Vulnerability.CVSS3Score),
301305
}
302306
}
303307

pkg/whitesource/reporting_test.go

+28-14
Original file line numberDiff line numberDiff line change
@@ -349,21 +349,31 @@ func TestGetAuditInformation(t *testing.T) {
349349
Status: "OPEN",
350350
},
351351
expected: &format.SarifProperties{
352-
Audited: false,
353-
ToolAuditMessage: "",
354-
UnifiedAuditState: "new",
352+
Audited: false,
353+
ToolAuditMessage: "",
354+
UnifiedAuditState: "new",
355+
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
356+
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
355357
},
356358
},
357359
{
358360
name: "Audited alert",
359361
alert: Alert{
360362
Status: "IGNORE",
361363
Comments: "Not relevant alert",
364+
Vulnerability: Vulnerability{
365+
CVSS3Score: 9.3,
366+
CVSS3Severity: "critical",
367+
},
362368
},
363369
expected: &format.SarifProperties{
364-
Audited: true,
365-
ToolAuditMessage: "Not relevant alert",
366-
UnifiedAuditState: "notRelevant",
370+
Audited: true,
371+
ToolAuditMessage: "Not relevant alert",
372+
UnifiedAuditState: "notRelevant",
373+
UnifiedSeverity: "critical",
374+
UnifiedCriticality: 9.3,
375+
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
376+
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
367377
},
368378
},
369379
{
@@ -373,13 +383,15 @@ func TestGetAuditInformation(t *testing.T) {
373383
Comments: "Some comment",
374384
},
375385
expected: &format.SarifProperties{
376-
Audited: false,
377-
ToolAuditMessage: "",
378-
UnifiedAuditState: "new",
386+
Audited: false,
387+
ToolAuditMessage: "",
388+
UnifiedAuditState: "new",
389+
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
390+
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
379391
},
380392
},
381393
{
382-
name: "Audited alert",
394+
name: "Not audited alert",
383395
alert: Alert{
384396
Assessment: &format.Assessment{
385397
Status: format.NotRelevant,
@@ -389,16 +401,18 @@ func TestGetAuditInformation(t *testing.T) {
389401
Comments: "New alert",
390402
},
391403
expected: &format.SarifProperties{
392-
Audited: true,
393-
ToolAuditMessage: string(format.FixedByDevTeam),
394-
UnifiedAuditState: "notRelevant",
404+
Audited: true,
405+
ToolAuditMessage: string(format.FixedByDevTeam),
406+
UnifiedAuditState: "notRelevant",
407+
AuditRequirement: format.AUDIT_REQUIREMENT_GROUP_1_DESC,
408+
AuditRequirementIndex: format.AUDIT_REQUIREMENT_GROUP_1_INDEX,
395409
},
396410
},
397411
}
398412

399413
for _, test := range tt {
400414
t.Run(test.name, func(t *testing.T) {
401-
assert.Equal(t, getAuditInformation(test.alert), test.expected)
415+
assert.Equal(t, test.expected, getAuditInformation(test.alert))
402416
})
403417
}
404418
}

0 commit comments

Comments
 (0)