github.com/jaylevin/jenkins-library@v1.230.4/pkg/blackduck/reporting.go (about)

     1  package blackduck
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"path/filepath"
     7  
     8  	"github.com/SAP/jenkins-library/pkg/format"
     9  	"github.com/SAP/jenkins-library/pkg/log"
    10  	"github.com/SAP/jenkins-library/pkg/piperutils"
    11  	"github.com/SAP/jenkins-library/pkg/reporting"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // CreateSarifResultFile creates a SARIF result from the Vulnerabilities that were brought up by the scan
    16  func CreateSarifResultFile(vulns *Vulnerabilities) *format.SARIF {
    17  	//Now, we handle the sarif
    18  	log.Entry().Debug("Creating SARIF file for data transfer")
    19  	var sarif format.SARIF
    20  	sarif.Schema = "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json"
    21  	sarif.Version = "2.1.0"
    22  	var wsRun format.Runs
    23  	sarif.Runs = append(sarif.Runs, wsRun)
    24  
    25  	//handle the tool object
    26  	tool := *new(format.Tool)
    27  	tool.Driver = *new(format.Driver)
    28  	tool.Driver.Name = "Blackduck Hub Detect"
    29  	tool.Driver.Version = "unknown"
    30  	tool.Driver.InformationUri = "https://community.synopsys.com/s/document-item?bundleId=integrations-detect&topicId=introduction.html&_LANG=enus"
    31  
    32  	// Handle results/vulnerabilities
    33  	if vulns != nil && vulns.Items != nil {
    34  		for i := 0; i < len(vulns.Items); i++ {
    35  			v := vulns.Items[i]
    36  			result := *new(format.Results)
    37  			id := v.Title()
    38  			log.Entry().Debugf("Transforming alert %v into SARIF format", id)
    39  			result.RuleID = id
    40  			result.Level = transformToLevel(v.VulnerabilityWithRemediation.Severity)
    41  			result.RuleIndex = i //Seems very abstract
    42  			result.Message = new(format.Message)
    43  			result.Message.Text = v.VulnerabilityWithRemediation.Description
    44  			result.AnalysisTarget = new(format.ArtifactLocation)
    45  			result.AnalysisTarget.URI = v.Name
    46  			result.AnalysisTarget.Index = 0
    47  			location := format.Location{PhysicalLocation: format.PhysicalLocation{ArtifactLocation: format.ArtifactLocation{URI: v.Name}}}
    48  			result.Locations = append(result.Locations, location)
    49  			//TODO add audit and tool related information, maybe fortifyCategory needs to become more general
    50  			//result.Properties = new(format.SarifProperties)
    51  			//result.Properties.ToolSeverity
    52  			//result.Properties.ToolAuditMessage
    53  
    54  			sarifRule := *new(format.SarifRule)
    55  			sarifRule.ID = id
    56  			sarifRule.ShortDescription = new(format.Message)
    57  			sarifRule.ShortDescription.Text = fmt.Sprintf("%v Package %v", v.VulnerabilityName, v.Name)
    58  			sarifRule.FullDescription = new(format.Message)
    59  			sarifRule.FullDescription.Text = v.VulnerabilityWithRemediation.Description
    60  			sarifRule.DefaultConfiguration = new(format.DefaultConfiguration)
    61  			sarifRule.DefaultConfiguration.Level = transformToLevel(v.VulnerabilityWithRemediation.Severity)
    62  			sarifRule.HelpURI = ""
    63  			markdown, _ := v.ToMarkdown()
    64  			sarifRule.Help = new(format.Help)
    65  			sarifRule.Help.Text = v.ToTxt()
    66  			sarifRule.Help.Markdown = string(markdown)
    67  
    68  			ruleProp := *new(format.SarifRuleProperties)
    69  			ruleProp.Tags = append(ruleProp.Tags, "SECURITY_VULNERABILITY")
    70  			ruleProp.Tags = append(ruleProp.Tags, v.VulnerabilityWithRemediation.Description)
    71  			ruleProp.Tags = append(ruleProp.Tags, v.Name)
    72  			ruleProp.Precision = "very-high"
    73  			sarifRule.Properties = &ruleProp
    74  
    75  			//Finalize: append the result and the rule
    76  			sarif.Runs[0].Results = append(sarif.Runs[0].Results, result)
    77  			tool.Driver.Rules = append(tool.Driver.Rules, sarifRule)
    78  		}
    79  	}
    80  	//Finalize: tool
    81  	sarif.Runs[0].Tool = tool
    82  
    83  	return &sarif
    84  }
    85  
    86  func transformToLevel(severity string) string {
    87  	switch severity {
    88  	case "LOW":
    89  		return "warning"
    90  	case "MEDIUM":
    91  		return "warning"
    92  	case "HIGH":
    93  		return "error"
    94  	case "CRITICAL":
    95  		return "error"
    96  	}
    97  	return "none"
    98  }
    99  
   100  // WriteVulnerabilityReports writes vulnerability information from ScanReport into dedicated outputs e.g. HTML
   101  func WriteVulnerabilityReports(scanReport reporting.ScanReport, utils piperutils.FileUtils) ([]piperutils.Path, error) {
   102  	reportPaths := []piperutils.Path{}
   103  
   104  	htmlReport, _ := scanReport.ToHTML()
   105  	htmlReportPath := "piper_detect_vulnerability_report.html"
   106  	if err := utils.FileWrite(htmlReportPath, htmlReport, 0666); err != nil {
   107  		log.SetErrorCategory(log.ErrorConfiguration)
   108  		return reportPaths, errors.Wrapf(err, "failed to write html report")
   109  	}
   110  	reportPaths = append(reportPaths, piperutils.Path{Name: "BlackDuck Vulnerability Report", Target: htmlReportPath})
   111  
   112  	jsonReport, _ := scanReport.ToJSON()
   113  	if exists, _ := utils.DirExists(reporting.StepReportDirectory); !exists {
   114  		err := utils.MkdirAll(reporting.StepReportDirectory, 0777)
   115  		if err != nil {
   116  			return reportPaths, errors.Wrap(err, "failed to create reporting directory")
   117  		}
   118  	}
   119  	if err := utils.FileWrite(filepath.Join(reporting.StepReportDirectory, fmt.Sprintf("detectExecuteScan_oss_%v.json", fmt.Sprintf("%v", utils.CurrentTime("")))), jsonReport, 0666); err != nil {
   120  		return reportPaths, errors.Wrapf(err, "failed to write json report")
   121  	}
   122  
   123  	return reportPaths, nil
   124  }
   125  
   126  // WriteSarifFile write a JSON sarif format file for upload into e.g. GCP
   127  func WriteSarifFile(sarif *format.SARIF, utils piperutils.FileUtils) ([]piperutils.Path, error) {
   128  	reportPaths := []piperutils.Path{}
   129  
   130  	// ignore templating errors since template is in our hands and issues will be detected with the automated tests
   131  	sarifReport, errorMarshall := json.Marshal(sarif)
   132  	if errorMarshall != nil {
   133  		return reportPaths, errors.Wrapf(errorMarshall, "failed to marshall SARIF json file")
   134  	}
   135  	if err := utils.MkdirAll(ReportsDirectory, 0777); err != nil {
   136  		return reportPaths, errors.Wrapf(err, "failed to create report directory")
   137  	}
   138  	sarifReportPath := filepath.Join(ReportsDirectory, "piper_detect_vulnerability.sarif")
   139  	if err := utils.FileWrite(sarifReportPath, sarifReport, 0666); err != nil {
   140  		log.SetErrorCategory(log.ErrorConfiguration)
   141  		return reportPaths, errors.Wrapf(err, "failed to write SARIF file")
   142  	}
   143  	reportPaths = append(reportPaths, piperutils.Path{Name: "Blackduck Detect Vulnerability SARIF file", Target: sarifReportPath})
   144  
   145  	return reportPaths, nil
   146  }