1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-10-30 23:57:50 +02:00

Simplify and gzip Fortify .sarif files (#4181)

* fix(Fortify):simplify plain text .sarif and gzip the complete result

* fix(Fortify):no longer add snippet text to .sarif to reduce file size (still keep end/start lines)

* fix: formatting
This commit is contained in:
thtri
2023-01-10 18:35:17 +01:00
committed by GitHub
parent 394196e76e
commit 844d4210ec
4 changed files with 151 additions and 80 deletions

View File

@@ -306,14 +306,21 @@ func runFortifyScan(ctx context.Context, config fortifyExecuteScanOptions, sys f
if config.ConvertToSarif {
resultFilePath := fmt.Sprintf("%vtarget/result.fpr", config.ModulePath)
log.Entry().Info("Calling conversion to SARIF function.")
sarif, err := fortify.ConvertFprToSarif(sys, projectVersion, resultFilePath, filterSet)
sarif, sarifSimplified, err := fortify.ConvertFprToSarif(sys, projectVersion, resultFilePath, filterSet)
if err != nil {
return reports, fmt.Errorf("failed to generate SARIF")
}
log.Entry().Debug("Writing sarif file to disk.")
paths, err := fortify.WriteSarif(sarif)
log.Entry().Debug("Writing simplified sarif file in plain text to disk.")
paths, err := fortify.WriteSarif(sarifSimplified, "result.sarif")
if err != nil {
return reports, fmt.Errorf("failed to write sarif")
return reports, fmt.Errorf("failed to write simplified sarif")
}
reports = append(reports, paths...)
log.Entry().Debug("Writing full sarif file to disk and gzip it.")
paths, err = fortify.WriteGzipSarif(sarif, "result.sarif.gz")
if err != nil {
return reports, fmt.Errorf("failed to write gzip sarif")
}
reports = append(reports, paths...)
}

View File

@@ -498,30 +498,31 @@ type Attribute struct {
}
// ConvertFprToSarif converts the FPR file contents into SARIF format
func ConvertFprToSarif(sys System, projectVersion *models.ProjectVersion, resultFilePath string, filterSet *models.FilterSet) (format.SARIF, error) {
func ConvertFprToSarif(sys System, projectVersion *models.ProjectVersion, resultFilePath string, filterSet *models.FilterSet) (format.SARIF, format.SARIF, error) {
log.Entry().Debug("Extracting FPR.")
var sarif format.SARIF
var sarifSimplified format.SARIF
tmpFolder, err := ioutil.TempDir(".", "temp-")
defer os.RemoveAll(tmpFolder)
if err != nil {
log.Entry().WithError(err).WithField("path", tmpFolder).Debug("Creating temp directory failed")
return sarif, err
return sarif, sarifSimplified, err
}
_, err = piperutils.Unzip(resultFilePath, tmpFolder)
if err != nil {
return sarif, err
return sarif, sarifSimplified, err
}
log.Entry().Debug("Reading audit file.")
data, err := ioutil.ReadFile(filepath.Join(tmpFolder, "audit.fvdl"))
if err != nil {
return sarif, err
return sarif, sarifSimplified, err
}
if len(data) == 0 {
log.Entry().Error("Error reading audit file at " + filepath.Join(tmpFolder, "audit.fvdl") + ". This might be that the file is missing, corrupted, or too large. Aborting procedure.")
err := errors.New("cannot read audit file")
return sarif, err
return sarif, sarifSimplified, err
}
log.Entry().Debug("Calling Parse.")
@@ -529,7 +530,7 @@ func ConvertFprToSarif(sys System, projectVersion *models.ProjectVersion, result
}
// Parse parses the FPR file
func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filterSet *models.FilterSet) (format.SARIF, error) {
func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filterSet *models.FilterSet) (format.SARIF, format.SARIF, error) {
//To read XML data, Unmarshal or Decode can be used, here we use Decode to work on the stream
reader := bytes.NewReader(data)
decoder := xml.NewDecoder(reader)
@@ -539,7 +540,7 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
var fvdl FVDL
err := decoder.Decode(&fvdl)
if err != nil {
return format.SARIF{}, err
return format.SARIF{}, format.SARIF{}, err
}
//Create an object containing all audit data
@@ -572,6 +573,12 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
cweIdsForTaxonomies := make(map[string]string) //Defining this here and filling it in the course of the program helps filling the Taxonomies object easily. Map because easy to check for keys
sarif.Runs = append(sarif.Runs, fortifyRun)
// Initialize the simplified version
var sarifSimplified format.SARIF
sarifSimplified.Schema = sarif.Schema
sarifSimplified.Version = sarif.Version
sarifSimplified.Runs = append(sarifSimplified.Runs, fortifyRun)
// Handle results/vulnerabilities
log.Entry().Debug("[SARIF] Now handling results.")
for i := 0; i < len(fvdl.Vulnerabilities.Vulnerability); i++ {
@@ -655,9 +662,6 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
tfloc.PhysicalLocation.ContextRegion = new(format.ContextRegion)
tfloc.PhysicalLocation.ContextRegion.StartLine = fvdl.Snippets[j].StartLine
tfloc.PhysicalLocation.ContextRegion.EndLine = fvdl.Snippets[j].EndLine
snippetSarif := new(format.SnippetSarif)
snippetSarif.Text = fvdl.Snippets[j].Text
tfloc.PhysicalLocation.ContextRegion.Snippet = snippetSarif
break
}
}
@@ -670,33 +674,6 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
if !(fvdl.Vulnerabilities.Vulnerability[i].AnalysisInfo.Trace[k].Primary.Entry[l].Node.Action.ActionData == "") {
tfloc.Message = new(format.Message)
tfloc.Message.Text = fvdl.Vulnerabilities.Vulnerability[i].AnalysisInfo.Trace[k].Primary.Entry[l].Node.Action.ActionData
// Handle snippet
snippetTarget := handleSnippet(fvdl.Vulnerabilities.Vulnerability[i].AnalysisInfo.Trace[k].Primary.Entry[l].Node.Action.Type, fvdl.Vulnerabilities.Vulnerability[i].AnalysisInfo.Trace[k].Primary.Entry[l].Node.Action.ActionData)
if tfloc.PhysicalLocation.ContextRegion != nil && tfloc.PhysicalLocation.ContextRegion.Snippet != nil {
physLocationSnippetLines := strings.Split(tfloc.PhysicalLocation.ContextRegion.Snippet.Text, "\n")
snippetText := ""
for j := 0; j < len(physLocationSnippetLines); j++ {
if strings.Contains(physLocationSnippetLines[j], snippetTarget) {
snippetText = physLocationSnippetLines[j]
break
}
}
snippetSarif := new(format.SnippetSarif)
if snippetText != "" {
snippetSarif.Text = snippetText
} else {
snippetSarif.Text = tfloc.PhysicalLocation.ContextRegion.Snippet.Text
}
tfloc.PhysicalLocation.Region.Snippet = snippetSarif
}
} else {
if tfloc.PhysicalLocation.ContextRegion != nil && tfloc.PhysicalLocation.ContextRegion.Snippet != nil {
snippetSarif := new(format.SnippetSarif)
snippetSarif.Text = tfloc.PhysicalLocation.ContextRegion.Snippet.Text
tfloc.PhysicalLocation.Region.Snippet = snippetSarif
}
}
}
location = *tfloc
@@ -739,9 +716,6 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
nintfloc.PhysicalLocation.ContextRegion = new(format.ContextRegion)
nintfloc.PhysicalLocation.ContextRegion.StartLine = fvdl.Snippets[j].StartLine
nintfloc.PhysicalLocation.ContextRegion.EndLine = fvdl.Snippets[j].EndLine
snippetSarif := new(format.SnippetSarif)
snippetSarif.Text = fvdl.Snippets[j].Text
nintfloc.PhysicalLocation.ContextRegion.Snippet = snippetSarif
break
}
}
@@ -806,6 +780,15 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
result.Properties = prop
sarif.Runs[0].Results = append(sarif.Runs[0].Results, result)
// Handle simplified version of a result
resultSimplified := *new(format.Results)
resultSimplified.RuleID = result.RuleID
resultSimplified.Kind = result.Kind
resultSimplified.Level = result.Level
resultSimplified.Message = result.Message
resultSimplified.Properties = result.Properties
sarifSimplified.Runs[0].Results = append(sarifSimplified.Runs[0].Results, resultSimplified)
}
//handle the tool object
@@ -816,6 +799,10 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
tool.Driver.Version = fvdl.EngineData.EngineVersion
tool.Driver.InformationUri = "https://www.microfocus.com/documentation/fortify-static-code-analyzer-and-tools/2020/SCA_Guide_20.2.0.pdf"
//handle the simplified tool object
toolSimplified := *new(format.Tool)
toolSimplified.Driver = tool.Driver
//handles rules
for i := 0; i < len(fvdl.EngineData.RuleInfo); i++ { //i iterates on rules
sarifRule := *new(format.SarifRule)
@@ -971,6 +958,15 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
//Finalize: append the rule
tool.Driver.Rules = append(tool.Driver.Rules, sarifRule)
// Handle simplified version of tool
sarifRuleSimplified := *new(format.SarifRule)
sarifRuleSimplified.ID = sarifRule.ID
sarifRuleSimplified.GUID = sarifRule.GUID
sarifRuleSimplified.Name = sarifRule.Name
sarifRuleSimplified.DefaultConfiguration = sarifRule.DefaultConfiguration
sarifRuleSimplified.Properties = sarifRule.Properties
toolSimplified.Driver.Rules = append(toolSimplified.Driver.Rules, sarifRuleSimplified)
// A rule vuln has been found for this rule, no need to keep iterating
break
}
@@ -994,6 +990,7 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
//Finalize: tool
sarif.Runs[0].Tool = tool
sarifSimplified.Runs[0].Tool = toolSimplified
//handle invocations object
log.Entry().Debug("[SARIF] Now handling invocation.")
@@ -1090,35 +1087,12 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
loc.PhysicalLocation.ContextRegion = new(format.ContextRegion)
loc.PhysicalLocation.ContextRegion.StartLine = fvdl.Snippets[j].StartLine
loc.PhysicalLocation.ContextRegion.EndLine = fvdl.Snippets[j].EndLine
snippetSarif := new(format.SnippetSarif)
snippetSarif.Text = fvdl.Snippets[j].Text
loc.PhysicalLocation.ContextRegion.Snippet = snippetSarif
break
}
}
loc.Message = new(format.Message)
loc.Message.Text = fvdl.UnifiedNodePool.Node[i].Action.ActionData
// Handle snippet
snippetTarget := handleSnippet(fvdl.UnifiedNodePool.Node[i].Action.Type, fvdl.UnifiedNodePool.Node[i].Action.ActionData)
if loc.PhysicalLocation.ContextRegion != nil && loc.PhysicalLocation.ContextRegion.Snippet != nil {
physLocationSnippetLines := strings.Split(loc.PhysicalLocation.ContextRegion.Snippet.Text, "\n")
snippetText := ""
for j := 0; j < len(physLocationSnippetLines); j++ {
if strings.Contains(physLocationSnippetLines[j], snippetTarget) {
snippetText = physLocationSnippetLines[j]
break
}
}
snippetSarif := new(format.SnippetSarif)
if snippetText != "" {
snippetSarif.Text = snippetText
} else {
snippetSarif.Text = loc.PhysicalLocation.ContextRegion.Snippet.Text
}
loc.PhysicalLocation.Region.Snippet = snippetSarif
}
log.Entry().Debug("Compute eventual sub-nodes")
threadFlowIndexMap[i+1] = computeLocationPath(fvdl, i+1) // Recursively traverse array
locs := format.Locations{Location: loc}
@@ -1180,7 +1154,7 @@ func Parse(sys System, projectVersion *models.ProjectVersion, data []byte, filte
}
sarif.Runs[0].Taxonomies = append(sarif.Runs[0].Taxonomies, taxonomy)
return sarif, nil
return sarif, sarifSimplified, nil
}
func integrateAuditData(ruleProp *format.SarifProperties, issueInstanceID string, sys System, projectVersion *models.ProjectVersion, auditData []*models.ProjectVersionIssue, filterSet *models.FilterSet, oneRequestPerIssue bool, maxretries int) error {
@@ -1301,6 +1275,8 @@ func integrateAuditData(ruleProp *format.SarifProperties, issueInstanceID string
}
// Factorizes some code used to obtain the relevant value for a snippet based on the type given by Fortify
// Note: snippet text is no longer part of .sarif due to size issue.
// This function however is helpful to explain how to get snippet out of FPR
func handleSnippet(snippetType string, snippet string) string {
snippetTarget := ""
switch snippetType {

View File

@@ -1,13 +1,12 @@
package fortify
import (
"net/http"
"strings"
"testing"
"github.com/SAP/jenkins-library/pkg/format"
"github.com/piper-validation/fortify-client-go/models"
"github.com/stretchr/testify/assert"
"net/http"
"strings"
"testing"
)
func TestParse(t *testing.T) {
@@ -361,30 +360,56 @@ If you are concerned about leaking system data via NFC on an Android device, you
t.Run("Valid config", func(t *testing.T) {
projectVersion := models.ProjectVersion{ID: 11037}
sarif, err := Parse(sys, &projectVersion, []byte(testFvdl), filterSet)
sarif, sarifSimplified, err := Parse(sys, &projectVersion, []byte(testFvdl), filterSet)
assert.NoError(t, err, "error")
assert.Equal(t, len(sarif.Runs[0].Results), 2)
assert.Equal(t, len(sarif.Runs[0].Results[0].Locations), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].CodeFlows), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].RelatedLocations), 1)
assert.Equal(t, len(sarif.Runs[0].Tool.Driver.Rules), 1)
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolState, "Exploitable")
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolAuditMessage, "Dummy comment.")
assert.Equal(t, sarif.Runs[0].OriginalUriBaseIds, &format.OriginalUriBaseIds{SrcRoot: format.SrcRoot{Uri: "file:///C:/fortify-reference-pipeline/"}})
//test simplified structure
assert.Equal(t, len(sarifSimplified.Runs[0].Results), 2) // same results
assert.Equal(t, len(sarifSimplified.Runs[0].Tool.Driver.Rules), 1) // same rules
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].Locations), 0) // without location
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].CodeFlows), 0) // without code flows
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].RelatedLocations), 0) // without related location
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolState, "Exploitable")
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolAuditMessage, "Dummy comment.")
assert.Equal(t, sarifSimplified.Runs[0].OriginalUriBaseIds, (*format.OriginalUriBaseIds)(nil)) // without OriginalUriBaseIds
})
t.Run("Missing data", func(t *testing.T) {
projectVersion := models.ProjectVersion{ID: 11037}
_, err := Parse(sys, &projectVersion, []byte{}, filterSet)
_, _, err := Parse(sys, &projectVersion, []byte{}, filterSet)
assert.Error(t, err, "EOF")
})
t.Run("No system instance", func(t *testing.T) {
projectVersion := models.ProjectVersion{ID: 11037}
sarif, err := Parse(nil, &projectVersion, []byte(testFvdl), filterSet)
sarif, sarifSimplified, err := Parse(nil, &projectVersion, []byte(testFvdl), filterSet)
assert.NoError(t, err, "error")
assert.Equal(t, len(sarif.Runs[0].Results), 2)
assert.Equal(t, len(sarif.Runs[0].Tool.Driver.Rules), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].Locations), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].CodeFlows), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].RelatedLocations), 1)
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolState, "Unknown")
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolAuditMessage, "Cannot fetch audit state: no sys instance")
assert.Equal(t, sarif.Runs[0].OriginalUriBaseIds, &format.OriginalUriBaseIds{SrcRoot: format.SrcRoot{Uri: "file:///C:/fortify-reference-pipeline/"}})
//test simplified structure
assert.Equal(t, len(sarifSimplified.Runs[0].Results), 2) // same results
assert.Equal(t, len(sarifSimplified.Runs[0].Tool.Driver.Rules), 1) // same rules
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].Locations), 0) // without location
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].CodeFlows), 0) // without code flows
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].RelatedLocations), 0) // without related location
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolState, "Unknown")
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolAuditMessage, "Cannot fetch audit state: no sys instance")
assert.Equal(t, sarifSimplified.Runs[0].OriginalUriBaseIds, (*format.OriginalUriBaseIds)(nil)) // without OriginalUriBaseIds
})
}
@@ -739,30 +764,55 @@ If you are concerned about leaking system data via NFC on an Android device, you
t.Run("Valid config", func(t *testing.T) {
projectVersion := models.ProjectVersion{ID: 11037}
sarif, err := Parse(sys, &projectVersion, []byte(testFvdl), filterSet)
sarif, sarifSimplified, err := Parse(sys, &projectVersion, []byte(testFvdl), filterSet)
assert.NoError(t, err, "error")
assert.Equal(t, len(sarif.Runs[0].Results), 2)
assert.Equal(t, len(sarif.Runs[0].Tool.Driver.Rules), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].Locations), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].CodeFlows), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].RelatedLocations), 1)
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolState, "Exploitable")
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolAuditMessage, "Dummy comment.")
assert.Equal(t, sarif.Runs[0].OriginalUriBaseIds, (*format.OriginalUriBaseIds)(nil))
// test simplified sarif structure
assert.Equal(t, len(sarifSimplified.Runs[0].Results), 2)
assert.Equal(t, len(sarifSimplified.Runs[0].Tool.Driver.Rules), 1)
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].Locations), 0)
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].CodeFlows), 0)
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].RelatedLocations), 0)
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolState, "Exploitable")
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolAuditMessage, "Dummy comment.")
assert.Equal(t, sarifSimplified.Runs[0].OriginalUriBaseIds, (*format.OriginalUriBaseIds)(nil))
})
t.Run("Missing data", func(t *testing.T) {
projectVersion := models.ProjectVersion{ID: 11037}
_, err := Parse(sys, &projectVersion, []byte{}, filterSet)
_, _, err := Parse(sys, &projectVersion, []byte{}, filterSet)
assert.Error(t, err, "EOF")
})
t.Run("No system instance", func(t *testing.T) {
projectVersion := models.ProjectVersion{ID: 11037}
sarif, err := Parse(nil, &projectVersion, []byte(testFvdl), filterSet)
sarif, sarifSimplified, err := Parse(nil, &projectVersion, []byte(testFvdl), filterSet)
assert.NoError(t, err, "error")
assert.Equal(t, len(sarif.Runs[0].Results), 2)
assert.Equal(t, len(sarif.Runs[0].Tool.Driver.Rules), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].Locations), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].CodeFlows), 1)
assert.Equal(t, len(sarif.Runs[0].Results[0].RelatedLocations), 1)
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolState, "Unknown")
assert.Equal(t, sarif.Runs[0].Results[0].Properties.ToolAuditMessage, "Cannot fetch audit state: no sys instance")
assert.Equal(t, sarif.Runs[0].OriginalUriBaseIds, (*format.OriginalUriBaseIds)(nil))
assert.Equal(t, len(sarifSimplified.Runs[0].Results), 2)
assert.Equal(t, len(sarifSimplified.Runs[0].Tool.Driver.Rules), 1)
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].Locations), 0)
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].CodeFlows), 0)
assert.Equal(t, len(sarifSimplified.Runs[0].Results[0].RelatedLocations), 0)
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolState, "Unknown")
assert.Equal(t, sarifSimplified.Runs[0].Results[0].Properties.ToolAuditMessage, "Cannot fetch audit state: no sys instance")
assert.Equal(t, sarifSimplified.Runs[0].OriginalUriBaseIds, (*format.OriginalUriBaseIds)(nil))
})
}

View File

@@ -2,6 +2,7 @@ package fortify
import (
"bytes"
"compress/gzip"
"crypto/sha1"
"encoding/json"
"fmt"
@@ -144,11 +145,11 @@ func WriteJSONReport(jsonReport FortifyReportData) ([]piperutils.Path, error) {
return reportPaths, nil
}
func WriteSarif(sarif format.SARIF) ([]piperutils.Path, error) {
func WriteSarif(sarif format.SARIF, fileName string) ([]piperutils.Path, error) {
utils := piperutils.Files{}
reportPaths := []piperutils.Path{}
sarifReportPath := filepath.Join(ReportsDirectory, "result.sarif")
sarifReportPath := filepath.Join(ReportsDirectory, fileName)
// Ensure reporting directory exists
if err := utils.MkdirAll(ReportsDirectory, 0777); err != nil {
return reportPaths, errors.Wrapf(err, "failed to create report directory")
@@ -177,6 +178,43 @@ func WriteSarif(sarif format.SARIF) ([]piperutils.Path, error) {
return reportPaths, nil
}
func WriteGzipSarif(sarif format.SARIF, fileName string) ([]piperutils.Path, error) {
utils := piperutils.Files{}
reportPaths := []piperutils.Path{}
sarifReportPath := filepath.Join(ReportsDirectory, fileName)
// Ensure reporting directory exists
if err := utils.MkdirAll(ReportsDirectory, 0777); err != nil {
return reportPaths, errors.Wrapf(err, "failed to create report directory")
}
// HTML characters will most likely be present: we need to use encode: create a buffer to hold JSON data
// https://stackoverflow.com/questions/28595664/how-to-stop-json-marshal-from-escaping-and
buffer := new(bytes.Buffer)
// create JSON encoder for buffer
bufEncoder := json.NewEncoder(buffer)
// set options
bufEncoder.SetEscapeHTML(false)
bufEncoder.SetIndent("", " ")
//encode to buffer
bufEncoder.Encode(sarif)
// Initialize gzip
gzBuffer := &bytes.Buffer{}
gzWriter := gzip.NewWriter(gzBuffer)
gzWriter.Write([]byte(buffer.Bytes()))
gzWriter.Close()
log.Entry().Info("Writing file to disk: ", sarifReportPath)
if err := utils.FileWrite(sarifReportPath, gzBuffer.Bytes(), 0666); err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return reportPaths, errors.Wrapf(err, "failed to write Fortify SARIF gzip report")
}
reportPaths = append(reportPaths, piperutils.Path{Name: "Fortify SARIF gzip Report", Target: sarifReportPath})
return reportPaths, nil
}
func WriteCustomReports(scanReport reporting.ScanReport) ([]piperutils.Path, error) {
utils := piperutils.Files{}
reportPaths := []piperutils.Path{}