1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-18 05:18:24 +02:00

Fix issue with not generating sarif file when projectName was specified (#4199)

* Fixed bug in generating sarif file in whitesource step

---------

Co-authored-by: sumeet patil <sumeet.patil@sap.com>
This commit is contained in:
Andrei Kireev 2023-02-07 16:10:21 +01:00 committed by GitHub
parent 501f7d214d
commit 27a3e687a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 142 additions and 65 deletions

View File

@ -587,100 +587,177 @@ func checkPolicyViolations(ctx context.Context, config *ScanOptions, scan *ws.Sc
}
func checkSecurityViolations(ctx context.Context, config *ScanOptions, scan *ws.Scan, sys whitesource, utils whitesourceUtils, influx *whitesourceExecuteScanInflux) ([]piperutils.Path, error) {
var reportPaths []piperutils.Path
// Check for security vulnerabilities and fail the build if cvssSeverityLimit threshold is crossed
// convert config.CvssSeverityLimit to float64
cvssSeverityLimit, err := strconv.ParseFloat(config.CvssSeverityLimit, 64)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return reportPaths, fmt.Errorf("failed to parse parameter cvssSeverityLimit (%s) "+
return []piperutils.Path{}, fmt.Errorf("failed to parse parameter cvssSeverityLimit (%s) "+
"as floating point number: %w", config.CvssSeverityLimit, err)
}
// inhale assessments from file system
assessments := readAssessmentsFromFile(config.AssessmentFile, utils)
vulnerabilitiesCount := 0
var allOccurredErrors []string
allAlerts := []ws.Alert{}
allAssessedAlerts := []ws.Alert{}
allLibraries := []ws.Library{}
if config.ProjectToken != "" {
project := ws.Project{Name: config.ProjectName, Token: config.ProjectToken}
// ToDo: see if HTML report generation is really required here
// we anyway need to do some refactoring here since config.ProjectToken != "" essentially indicates an aggregated project
if _, _, _, err := checkProjectSecurityViolations(config, cvssSeverityLimit, project, sys, assessments, influx); err != nil {
return reportPaths, err
}
vulnerabilitiesCount, allAlerts, allAssessedAlerts, allLibraries, allOccurredErrors = collectVulnsAndLibsForProject(
config,
cvssSeverityLimit,
project,
sys,
assessments,
influx,
)
log.Entry().Debugf("Collected %v libraries for project %v", len(allLibraries), project.Name)
} else {
vulnerabilitiesCount := 0
var errorsOccured []string
allAlerts := []ws.Alert{}
allAssessedAlerts := []ws.Alert{}
allLibraries := []ws.Library{}
for _, project := range scan.ScannedProjects() {
// collect errors and aggregate vulnerabilities from all projects
vulCount, alerts, assessedAlerts, err := checkProjectSecurityViolations(config, cvssSeverityLimit, project, sys, assessments, influx)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
vulCount, alerts, assessedAlerts, libraries, occurredErrors := collectVulnsAndLibsForProject(
config,
cvssSeverityLimit,
project,
sys,
assessments,
influx,
)
if len(occurredErrors) != 0 {
allOccurredErrors = append(allOccurredErrors, occurredErrors...)
}
allAlerts = append(allAlerts, alerts...)
allAssessedAlerts = append(allAssessedAlerts, assessedAlerts...)
vulnerabilitiesCount += vulCount
// collect all libraries detected in all related projects and errors
libraries, err := sys.GetProjectHierarchy(project.Token, true)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
log.Entry().Debugf("Collected %v libraries for project %v", len(libraries), project.Name)
allLibraries = append(allLibraries, libraries...)
}
log.Entry().Debugf("Aggregated %v alerts for scanned projects", len(allAlerts))
}
if config.CreateResultIssue && vulnerabilitiesCount > 0 && len(config.GithubToken) > 0 && len(config.GithubAPIURL) > 0 && len(config.Owner) > 0 && len(config.Repository) > 0 {
log.Entry().Debugf("Creating result issues for %v alert(s)", vulnerabilitiesCount)
issueDetails := make([]reporting.IssueDetail, len(allAlerts))
piperutils.CopyAtoB(allAlerts, issueDetails)
gh := reporting.GitHub{
Owner: &config.Owner,
Repository: &config.Repository,
Assignees: &config.Assignees,
IssueService: utils.GetIssueService(),
SearchService: utils.GetSearchService(),
}
if err := gh.UploadMultipleReports(ctx, &issueDetails); err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths, errors := reportGitHubIssuesAndCreateReports(
ctx,
config,
utils,
scan,
allAlerts,
allLibraries,
allAssessedAlerts,
cvssSeverityLimit,
vulnerabilitiesCount,
)
allOccurredErrors = append(allOccurredErrors, errors...)
if len(allOccurredErrors) > 0 {
if vulnerabilitiesCount > 0 {
log.SetErrorCategory(log.ErrorCompliance)
}
return reportPaths, fmt.Errorf(strings.Join(allOccurredErrors, ": "))
}
return reportPaths, nil
}
func collectVulnsAndLibsForProject(
config *ScanOptions,
cvssSeverityLimit float64,
project ws.Project,
sys whitesource,
assessments *[]format.Assessment,
influx *whitesourceExecuteScanInflux,
) (
int,
[]ws.Alert,
[]ws.Alert,
[]ws.Library,
[]string,
) {
var errorsOccurred []string
vulCount, alerts, assessedAlerts, err := checkProjectSecurityViolations(config, cvssSeverityLimit, project, sys, assessments, influx)
if err != nil {
errorsOccurred = append(errorsOccurred, fmt.Sprint(err))
}
// collect all libraries detected in all related projects and errors
libraries, err := sys.GetProjectHierarchy(project.Token, true)
if err != nil {
errorsOccurred = append(errorsOccurred, fmt.Sprint(err))
}
log.Entry().Debugf("Collected %v libraries for project %v", len(libraries), project.Name)
return vulCount, alerts, assessedAlerts, libraries, errorsOccurred
}
func reportGitHubIssuesAndCreateReports(
ctx context.Context,
config *ScanOptions,
utils whitesourceUtils,
scan *ws.Scan,
allAlerts []ws.Alert,
allLibraries []ws.Library,
allAssessedAlerts []ws.Alert,
cvssSeverityLimit float64,
vulnerabilitiesCount int,
) ([]piperutils.Path, []string) {
errorsOccured := make([]string, 0)
reportPaths := make([]piperutils.Path, 0)
if config.CreateResultIssue && vulnerabilitiesCount > 0 && len(config.GithubToken) > 0 && len(config.GithubAPIURL) > 0 && len(config.Owner) > 0 && len(config.Repository) > 0 {
log.Entry().Debugf("Creating result issues for %v alert(s)", vulnerabilitiesCount)
issueDetails := make([]reporting.IssueDetail, len(allAlerts))
piperutils.CopyAtoB(allAlerts, issueDetails)
gh := reporting.GitHub{
Owner: &config.Owner,
Repository: &config.Repository,
Assignees: &config.Assignees,
IssueService: utils.GetIssueService(),
SearchService: utils.GetSearchService(),
}
scanReport := ws.CreateCustomVulnerabilityReport(config.ProductName, scan, &allAlerts, cvssSeverityLimit)
paths, err := ws.WriteCustomVulnerabilityReports(config.ProductName, scan, scanReport, utils)
if err != nil {
if err := gh.UploadMultipleReports(ctx, &issueDetails); err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths = append(reportPaths, paths...)
sarif := ws.CreateSarifResultFile(scan, &allAlerts)
paths, err = ws.WriteSarifFile(sarif, utils)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths = append(reportPaths, paths...)
sbom, err := ws.CreateCycloneSBOM(scan, &allLibraries, &allAlerts, &allAssessedAlerts)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
paths, err = ws.WriteCycloneSBOM(sbom, utils)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths = append(reportPaths, paths...)
if len(errorsOccured) > 0 {
if vulnerabilitiesCount > 0 {
log.SetErrorCategory(log.ErrorCompliance)
}
return reportPaths, fmt.Errorf(strings.Join(errorsOccured, ": "))
}
}
return reportPaths, nil
scanReport := ws.CreateCustomVulnerabilityReport(config.ProductName, scan, &allAlerts, cvssSeverityLimit)
paths, err := ws.WriteCustomVulnerabilityReports(config.ProductName, scan, scanReport, utils)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths = append(reportPaths, paths...)
sarif := ws.CreateSarifResultFile(scan, &allAlerts)
paths, err = ws.WriteSarifFile(sarif, utils)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths = append(reportPaths, paths...)
sbom, err := ws.CreateCycloneSBOM(scan, &allLibraries, &allAlerts, &allAssessedAlerts)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
paths, err = ws.WriteCycloneSBOM(sbom, utils)
if err != nil {
errorsOccured = append(errorsOccured, fmt.Sprint(err))
}
reportPaths = append(reportPaths, paths...)
return reportPaths, errorsOccured
}
// read assessments from file and expose them to match alerts and filter them before processing

View File

@ -595,7 +595,7 @@ func TestCheckSecurityViolations(t *testing.T) {
reportPaths, err := checkSecurityViolations(ctx, &config, scan, systemMock, utilsMock, &influx)
assert.NoError(t, err)
assert.Equal(t, 0, len(reportPaths))
assert.Equal(t, 3, len(reportPaths))
})
t.Run("error - wrong limit", func(t *testing.T) {
@ -651,7 +651,7 @@ func TestCheckSecurityViolations(t *testing.T) {
reportPaths, err := checkSecurityViolations(ctx, &config, scan, systemMock, utilsMock, &influx)
assert.Contains(t, fmt.Sprint(err), "1 Open Source Software Security vulnerabilities")
assert.Equal(t, 0, len(reportPaths))
assert.Equal(t, 3, len(reportPaths))
})
}