1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-03-05 15:15:44 +02:00

feat(sarif): add a "conversion" object to SARIF files (#3837)

* feat(fortifyExecuteScan): add conversion object

* feat(checkmarxExecuteScan): add conversion object
This commit is contained in:
xgoffin 2022-06-16 15:24:23 +02:00 committed by GitHub
parent 6ab3ab2841
commit c11110d791
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 12 deletions

View File

@ -3,9 +3,11 @@ package checkmarx
import ( import (
"bytes" "bytes"
"encoding/xml" "encoding/xml"
"fmt"
"io/ioutil" "io/ioutil"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/SAP/jenkins-library/pkg/format" "github.com/SAP/jenkins-library/pkg/format"
"github.com/SAP/jenkins-library/pkg/log" "github.com/SAP/jenkins-library/pkg/log"
@ -136,6 +138,8 @@ func Parse(sys System, data []byte, scanID int) (format.SARIF, error) {
reader := bytes.NewReader(data) reader := bytes.NewReader(data)
decoder := xml.NewDecoder(reader) decoder := xml.NewDecoder(reader)
start := time.Now() // For the conversion start time
var cxxml CxXMLResults var cxxml CxXMLResults
err := decoder.Decode(&cxxml) err := decoder.Decode(&cxxml)
if err != nil { if err != nil {
@ -350,5 +354,14 @@ func Parse(sys System, data []byte, scanID int) (format.SARIF, error) {
} }
sarif.Runs[0].Taxonomies = append(sarif.Runs[0].Taxonomies, taxonomy) sarif.Runs[0].Taxonomies = append(sarif.Runs[0].Taxonomies, taxonomy)
// Add a conversion object to highlight this isn't native SARIF
conversion := new(format.Conversion)
conversion.Tool.Driver.Name = "Piper Checkmarx XML to SARIF converter"
conversion.Tool.Driver.InformationUri = "https://github.com/SAP/jenkins-library"
conversion.Invocation.ExecutionSuccessful = true
conversion.Invocation.StartTimeUtc = fmt.Sprintf("%s", start.Format("2006-01-02T15:04:05.000Z")) // "YYYY-MM-DDThh:mm:ss.sZ" on 2006-01-02 15:04:05
conversion.Invocation.Account = cxxml.InitiatorName
sarif.Runs[0].Conversion = conversion
return sarif, nil return sarif, nil
} }

View File

@ -11,13 +11,14 @@ type SARIF struct {
type Runs struct { type Runs struct {
Results []Results `json:"results"` Results []Results `json:"results"`
Tool Tool `json:"tool"` Tool Tool `json:"tool"`
Invocations []Invocations `json:"invocations,omitempty"` Invocations []Invocation `json:"invocations,omitempty"`
OriginalUriBaseIds *OriginalUriBaseIds `json:"originalUriBaseIds,omitempty"` OriginalUriBaseIds *OriginalUriBaseIds `json:"originalUriBaseIds,omitempty"`
Artifacts []Artifact `json:"artifacts,omitempty"` Artifacts []Artifact `json:"artifacts,omitempty"`
AutomationDetails AutomationDetails `json:"automationDetails,omitempty"` AutomationDetails AutomationDetails `json:"automationDetails,omitempty"`
ColumnKind string `json:"columnKind,omitempty" default:"utf16CodeUnits"` ColumnKind string `json:"columnKind,omitempty" default:"utf16CodeUnits"`
ThreadFlowLocations []Locations `json:"threadFlowLocations,omitempty"` ThreadFlowLocations []Locations `json:"threadFlowLocations,omitempty"`
Taxonomies []Taxonomies `json:"taxonomies,omitempty"` Taxonomies []Taxonomies `json:"taxonomies,omitempty"`
Conversion *Conversion `json:"conversion,omitempty"`
} }
// Results these structs are relevant to the Results object // Results these structs are relevant to the Results object
@ -109,7 +110,7 @@ type Tool struct {
// Driver meta information for the scan and tool context // Driver meta information for the scan and tool context
type Driver struct { type Driver struct {
Name string `json:"name"` Name string `json:"name"`
Version string `json:"version"` Version string `json:"version,omitempty"`
GUID string `json:"guid,omitempty"` GUID string `json:"guid,omitempty"`
InformationUri string `json:"informationUri,omitempty"` InformationUri string `json:"informationUri,omitempty"`
Rules []SarifRule `json:"rules,omitempty"` Rules []SarifRule `json:"rules,omitempty"`
@ -231,15 +232,15 @@ type SarifRuleProperties struct {
SecuritySeverity string `json:"security-severity,omitempty"` //used by GHAS to defined the tag (low,medium,high) SecuritySeverity string `json:"security-severity,omitempty"` //used by GHAS to defined the tag (low,medium,high)
} }
// Invocations These structs are relevant to the Invocations object // Invocation These structs are relevant to the Invocation object
type Invocations struct { type Invocation struct {
CommandLine string `json:"commandLine"` CommandLine string `json:"commandLine,omitempty"`
StartTimeUtc string `json:"startTimeUtc"` StartTimeUtc string `json:"startTimeUtc,omitempty"`
ToolExecutionNotifications []ToolExecutionNotifications `json:"toolExecutionNotifications"` ToolExecutionNotifications []ToolExecutionNotifications `json:"toolExecutionNotifications,omitempty"`
ExecutionSuccessful bool `json:"executionSuccessful"` ExecutionSuccessful bool `json:"executionSuccessful"`
Machine string `json:"machine"` Machine string `json:"machine,omitempty"`
Account string `json:"account"` Account string `json:"account,omitempty"`
Properties InvocationProperties `json:"properties"` Properties *InvocationProperties `json:"properties,omitempty"`
} }
// ToolExecutionNotifications // ToolExecutionNotifications
@ -302,3 +303,9 @@ type Taxonomies struct {
type Taxa struct { type Taxa struct {
Id string `json:"id"` Id string `json:"id"`
} }
// Conversion object
type Conversion struct {
Tool Tool `json:"tool,omitempty"`
Invocation Invocation `json:"invocation,omitempty"`
}

View File

@ -10,6 +10,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/piper-validation/fortify-client-go/models" "github.com/piper-validation/fortify-client-go/models"
@ -532,6 +533,8 @@ func Parse(sys System, project *models.Project, projectVersion *models.ProjectVe
reader := bytes.NewReader(data) reader := bytes.NewReader(data)
decoder := xml.NewDecoder(reader) decoder := xml.NewDecoder(reader)
start := time.Now() // For the conversion start time
var fvdl FVDL var fvdl FVDL
err := decoder.Decode(&fvdl) err := decoder.Decode(&fvdl)
if err != nil { if err != nil {
@ -990,7 +993,7 @@ func Parse(sys System, project *models.Project, projectVersion *models.ProjectVe
//handle invocations object //handle invocations object
log.Entry().Debug("[SARIF] Now handling invocation.") log.Entry().Debug("[SARIF] Now handling invocation.")
invocation := *new(format.Invocations) invocation := *new(format.Invocation)
for i := 0; i < len(fvdl.EngineData.Properties); i++ { //i selects the properties type for i := 0; i < len(fvdl.EngineData.Properties); i++ { //i selects the properties type
if fvdl.EngineData.Properties[i].PropertiesType == "Fortify" { // This is the correct type, now iterate on props if fvdl.EngineData.Properties[i].PropertiesType == "Fortify" { // This is the correct type, now iterate on props
for j := 0; j < len(fvdl.EngineData.Properties[i].Property); j++ { for j := 0; j < len(fvdl.EngineData.Properties[i].Property); j++ {
@ -1014,7 +1017,9 @@ func Parse(sys System, project *models.Project, projectVersion *models.ProjectVe
invocation.ExecutionSuccessful = true //fvdl doesn't seem to plan for this setting invocation.ExecutionSuccessful = true //fvdl doesn't seem to plan for this setting
invocation.Machine = fvdl.EngineData.MachineInfo.Hostname invocation.Machine = fvdl.EngineData.MachineInfo.Hostname
invocation.Account = fvdl.EngineData.MachineInfo.Username invocation.Account = fvdl.EngineData.MachineInfo.Username
invocation.Properties.Platform = fvdl.EngineData.MachineInfo.Platform invocProp := new(format.InvocationProperties)
invocProp.Platform = fvdl.EngineData.MachineInfo.Platform
invocation.Properties = invocProp
sarif.Runs[0].Invocations = append(sarif.Runs[0].Invocations, invocation) sarif.Runs[0].Invocations = append(sarif.Runs[0].Invocations, invocation)
//handle originalUriBaseIds //handle originalUriBaseIds
@ -1139,6 +1144,19 @@ func Parse(sys System, project *models.Project, projectVersion *models.ProjectVe
// Threadflowlocations is no loger useful: voiding it will make for smaller reports // Threadflowlocations is no loger useful: voiding it will make for smaller reports
sarif.Runs[0].ThreadFlowLocations = []format.Locations{} sarif.Runs[0].ThreadFlowLocations = []format.Locations{}
// Add a conversion object to highlight this isn't native SARIF
conversion := new(format.Conversion)
conversion.Tool.Driver.Name = "Piper FPR to SARIF converter"
conversion.Tool.Driver.InformationUri = "https://github.com/SAP/jenkins-library"
conversion.Invocation.ExecutionSuccessful = true
conversion.Invocation.StartTimeUtc = fmt.Sprintf("%s", start.Format("2006-01-02T15:04:05.000Z")) // "YYYY-MM-DDThh:mm:ss.sZ" on 2006-01-02 15:04:05
conversion.Invocation.Machine = fvdl.EngineData.MachineInfo.Hostname
conversion.Invocation.Account = fvdl.EngineData.MachineInfo.Username
convInvocProp := new(format.InvocationProperties)
convInvocProp.Platform = fvdl.EngineData.MachineInfo.Platform
conversion.Invocation.Properties = convInvocProp
sarif.Runs[0].Conversion = conversion
//handle taxonomies //handle taxonomies
//Only one exists apparently: CWE. It is fixed //Only one exists apparently: CWE. It is fixed
taxonomy := *new(format.Taxonomies) taxonomy := *new(format.Taxonomies)