Skip to content

Commit

Permalink
refactor handling sarif, describe better
Browse files Browse the repository at this point in the history
  • Loading branch information
attiasas committed Aug 30, 2023
1 parent b1383d2 commit fe4d4c4
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 140 deletions.
27 changes: 18 additions & 9 deletions xray/audit/jas/jasmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,31 +128,40 @@ func deleteJasProcessFiles(configFile string, resultFile string) error {
}

func getSourceCodeScanResults(resultsFileName, workingDir string, scanType utils.JasScanType) ([]utils.SourceCodeScanResult, error) {
// Read Sarif format results generated from the Jas scanner
report, err := sarif.Open(resultsFileName)
if errorutils.CheckError(err) != nil {
return nil, err
}
var results []*sarif.Result
var sarifResults []*sarif.Result
if len(report.Runs) > 0 {
results = report.Runs[0].Results
// Jas scanners returns results in a single run entry
sarifResults = report.Runs[0].Results
}
return convertSarifResultsToSourceCodeScanResults(sarifResults, workingDir, scanType), nil
}

func convertSarifResultsToSourceCodeScanResults(sarifResults []*sarif.Result, workingDir string, scanType utils.JasScanType) []utils.SourceCodeScanResult {
var sourceCodeScanResults []utils.SourceCodeScanResult
for _, result := range results {
for _, sarifResult := range sarifResults {
// Describes a request to “suppress” a result (to exclude it from result lists)
if len(result.Suppressions) > 0 {
if len(sarifResult.Suppressions) > 0 {
continue
}
index := utils.GetOrCreateCodeScanResult(result, workingDir, &sourceCodeScanResults)
// Convert
sourceCodeScanResult := utils.IsSarifResultExistsInSourceCodeScanResults(sarifResult, workingDir, &sourceCodeScanResults)
if sourceCodeScanResult == nil {
sourceCodeScanResult = utils.ConvertSarifResultToSourceCodeScanResult(sarifResult, workingDir, &sourceCodeScanResults)
}
// Set specific Jas scan attributes
if scanType == utils.Secrets {
sourceCodeScanResults[index].Text = hideSecret(utils.GetResultLocationSnippet(result.Locations[0]))
sourceCodeScanResult.Text = hideSecret(utils.GetResultLocationSnippet(sarifResult.Locations[0]))
}
if scanType == utils.Sast {
flows := utils.GetResultCodeFlows(result, workingDir)
sourceCodeScanResults[index].CodeFlow = append(sourceCodeScanResults[index].CodeFlow, flows...)
sourceCodeScanResult.CodeFlow = append(sourceCodeScanResult.CodeFlow, utils.GetResultCodeFlows(sarifResult, workingDir)...)
}
}
return sourceCodeScanResults, nil
return sourceCodeScanResults
}

func createScannersConfigFile(fileName string, fileContent interface{}) error {
Expand Down
131 changes: 0 additions & 131 deletions xray/utils/analyzermanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,13 @@ import (
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray/services"
"github.com/owenrumney/go-sarif/v2/sarif"
)

var (
Expand Down Expand Up @@ -210,134 +207,6 @@ func RemoveDuplicateValues(stringSlice []string) []string {
return finalSlice
}

func GetResultIndexIfExists(file, lineCol, text string, results []SourceCodeScanResult) int {
for i, result := range results {
if result.File == file && result.LineColumn == lineCol && result.Text == text {
return i
}
}
return -1
}

// If a result with the same file, line, column and text exists return it. otherwise create a new result and add it to results
// Used to combine results from similar places instead of reporting multiple duplicate rows
func GetOrCreateCodeScanResult(result *sarif.Result, workingDir string, results *[]SourceCodeScanResult) int {
file := ExtractRelativePath(GetResultFileName(result), workingDir)
lineCol := GetResultLocationInFile(result)
text := *result.Message.Text
// Already exists
if index := GetResultIndexIfExists(file, lineCol, text, *results); index >= 0 {
return index
}
// New result
newResult := SourceCodeScanResult{
Severity: GetResultSeverity(result),
SourceCodeLocation: SourceCodeLocation{
File: file,
LineColumn: lineCol,
Text: text,
},
Type: *result.RuleID,
}
index := len(*results)
*results = append(*results, newResult)

return index
}

func GetResultFileName(result *sarif.Result) string {
if len(result.Locations) > 0 {
return getResultFileName(result.Locations[0])
}
return ""
}

func getResultFileName(location *sarif.Location) string {
filePath := location.PhysicalLocation.ArtifactLocation.URI
if filePath != nil {
return *filePath
}
return ""
}

func GetResultLocationInFile(result *sarif.Result) string {
if len(result.Locations) > 0 {
return getResultLocationInFile(result.Locations[0])
}
return ""
}

func getResultLocationInFile(location *sarif.Location) string {
startLine := location.PhysicalLocation.Region.StartLine
startColumn := location.PhysicalLocation.Region.StartColumn
if startLine != nil && startColumn != nil {
return strconv.Itoa(*startLine) + ":" + strconv.Itoa(*startColumn)
}
return ""
}

func GetResultLocationSnippet(location *sarif.Location) string {
if location != nil && location.PhysicalLocation != nil && location.PhysicalLocation.Region != nil && location.PhysicalLocation.Region.Snippet != nil {
return *location.PhysicalLocation.Region.Snippet.Text
}
return ""
}

func GetResultCodeFlows(result *sarif.Result, workingDir string) (flows [][]SourceCodeLocation) {
if len(result.CodeFlows) == 0 {
return
}
for _, codeFlow := range result.CodeFlows {
if codeFlow == nil || len(codeFlow.ThreadFlows) == 0 {
continue
}
flows = append(flows, extractThreadFlows(codeFlow.ThreadFlows, workingDir)...)
}
return
}

func extractThreadFlows(threadFlows []*sarif.ThreadFlow, workingDir string) (flows [][]SourceCodeLocation) {
for _, threadFlow := range threadFlows {
if threadFlow == nil || len(threadFlow.Locations) == 0 {
continue
}
flow := extractStackTraceLocations(threadFlow.Locations, workingDir)
if len(flow) > 0 {
flows = append(flows, flow)
}
}
return
}

func extractStackTraceLocations(locations []*sarif.ThreadFlowLocation, workingDir string) (flow []SourceCodeLocation) {
for _, location := range locations {
if location == nil {
continue
}
flow = append(flow, SourceCodeLocation{
File: ExtractRelativePath(getResultFileName(location.Location), workingDir),
LineColumn: getResultLocationInFile(location.Location),
Text: GetResultLocationSnippet(location.Location),
})
}
return
}

func ExtractRelativePath(resultPath string, projectRoot string) string {
filePrefix := "file://"
relativePath := strings.ReplaceAll(strings.ReplaceAll(resultPath, projectRoot, ""), filePrefix, "")
return relativePath
}

func GetResultSeverity(result *sarif.Result) string {
if result.Level != nil {
if severity, ok := levelToSeverity[*result.Level]; ok {
return severity
}
}
return SeverityDefaultValue
}

// Receives a list of relative path working dirs, returns a list of full paths working dirs
func GetFullPathsWorkingDirs(workingDirs []string) ([]string, error) {
if len(workingDirs) == 0 {
Expand Down
130 changes: 130 additions & 0 deletions xray/utils/sarifutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package utils

import (
"strconv"
"strings"

"github.com/owenrumney/go-sarif/v2/sarif"
)

// If exists SourceCodeScanResult with the same location as the provided SarifResult, return it
func IsSarifResultExistsInSourceCodeScanResults(result *sarif.Result, workingDir string, results *[]SourceCodeScanResult) *SourceCodeScanResult {
file := ExtractRelativePath(GetResultFileName(result), workingDir)
lineCol := GetResultLocationInFile(result)
text := *result.Message.Text
for _, result := range *results {
if result.File == file && result.LineColumn == lineCol && result.Text == text {
return &result
}
}
return nil
}

func ConvertSarifResultToSourceCodeScanResult(result *sarif.Result, workingDir string, results *[]SourceCodeScanResult) *SourceCodeScanResult {
file := ExtractRelativePath(GetResultFileName(result), workingDir)
lineCol := GetResultLocationInFile(result)
text := *result.Message.Text

return &SourceCodeScanResult{
Severity: GetResultSeverity(result),
SourceCodeLocation: SourceCodeLocation{
File: file,
LineColumn: lineCol,
Text: text,
},
Type: *result.RuleID,
}
}

func GetResultCodeFlows(result *sarif.Result, workingDir string) (flows [][]SourceCodeLocation) {
if len(result.CodeFlows) == 0 {
return
}
for _, codeFlow := range result.CodeFlows {
if codeFlow == nil || len(codeFlow.ThreadFlows) == 0 {
continue
}
flows = append(flows, extractThreadFlows(codeFlow.ThreadFlows, workingDir)...)
}
return
}

func extractThreadFlows(threadFlows []*sarif.ThreadFlow, workingDir string) (flows [][]SourceCodeLocation) {
for _, threadFlow := range threadFlows {
if threadFlow == nil || len(threadFlow.Locations) == 0 {
continue
}
flow := extractStackTraceLocations(threadFlow.Locations, workingDir)
if len(flow) > 0 {
flows = append(flows, flow)
}
}
return
}

func extractStackTraceLocations(locations []*sarif.ThreadFlowLocation, workingDir string) (flow []SourceCodeLocation) {
for _, location := range locations {
if location == nil {
continue
}
flow = append(flow, SourceCodeLocation{
File: ExtractRelativePath(getResultFileName(location.Location), workingDir),
LineColumn: getResultLocationInFile(location.Location),
Text: GetResultLocationSnippet(location.Location),
})
}
return
}

func GetResultLocationSnippet(location *sarif.Location) string {
if location != nil && location.PhysicalLocation != nil && location.PhysicalLocation.Region != nil && location.PhysicalLocation.Region.Snippet != nil {
return *location.PhysicalLocation.Region.Snippet.Text
}
return ""
}

func GetResultFileName(result *sarif.Result) string {
if len(result.Locations) > 0 {
return getResultFileName(result.Locations[0])
}
return ""
}

func getResultFileName(location *sarif.Location) string {
filePath := location.PhysicalLocation.ArtifactLocation.URI
if filePath != nil {
return *filePath
}
return ""
}

func GetResultLocationInFile(result *sarif.Result) string {
if len(result.Locations) > 0 {
return getResultLocationInFile(result.Locations[0])
}
return ""
}

func getResultLocationInFile(location *sarif.Location) string {
startLine := location.PhysicalLocation.Region.StartLine
startColumn := location.PhysicalLocation.Region.StartColumn
if startLine != nil && startColumn != nil {
return strconv.Itoa(*startLine) + ":" + strconv.Itoa(*startColumn)
}
return ""
}

func ExtractRelativePath(resultPath string, projectRoot string) string {
filePrefix := "file://"
relativePath := strings.ReplaceAll(strings.ReplaceAll(resultPath, projectRoot, ""), filePrefix, "")
return relativePath
}

func GetResultSeverity(result *sarif.Result) string {
if result.Level != nil {
if severity, ok := levelToSeverity[*result.Level]; ok {
return severity
}
}
return SeverityDefaultValue
}

0 comments on commit fe4d4c4

Please sign in to comment.