Skip to content

Commit

Permalink
Add new unified fields to Mend and Blackduck SARIF (#4611)
Browse files Browse the repository at this point in the history
* Add new unified fields to Mend and Blackduck SARIF

* fmt project

---------

Co-authored-by: Dmitrii Pavlukhin <[email protected]>
  • Loading branch information
andrew-kireev and dimaste authored Oct 17, 2023
1 parent 3761a9f commit 49f4c81
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 56 deletions.
29 changes: 8 additions & 21 deletions cmd/whitesourceExecuteScan.go
Original file line number Diff line number Diff line change
Expand Up @@ -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...)
}
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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{}
Expand Down Expand Up @@ -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...)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/blackduck/blackduck.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 12 additions & 6 deletions pkg/blackduck/reporting.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"path/filepath"
"runtime"
"strings"

"github.com/SAP/jenkins-library/pkg/format"
"github.com/SAP/jenkins-library/pkg/log"
Expand Down Expand Up @@ -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,
},
}

Expand Down
9 changes: 9 additions & 0 deletions pkg/blackduck/reporting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
},
{
Expand Down Expand Up @@ -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",
},
},
{
Expand Down Expand Up @@ -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,
Expand Down
25 changes: 14 additions & 11 deletions pkg/format/sarif.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
12 changes: 8 additions & 4 deletions pkg/whitesource/reporting.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
}
}

Expand Down
42 changes: 28 additions & 14 deletions pkg/whitesource/reporting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,21 +349,31 @@ 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,
},
},
{
name: "Audited alert",
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,
},
},
{
Expand All @@ -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,
Expand All @@ -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))
})
}
}

0 comments on commit 49f4c81

Please sign in to comment.