Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add summary format #63

Merged
merged 45 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9cdb652
Add Github summary for commands
attiasas May 9, 2024
b126785
format
attiasas May 9, 2024
1ac3a36
compile
attiasas May 9, 2024
7dae69c
update core changes
attiasas May 9, 2024
15e8483
use impl
attiasas May 9, 2024
abe9d62
json attributes
attiasas May 9, 2024
c7a82e2
update core
attiasas May 9, 2024
e40b98b
add space
attiasas May 9, 2024
c05d9d6
update core
attiasas May 9, 2024
83bddb7
add subscans GUI
attiasas May 9, 2024
9cb8687
update core
attiasas May 9, 2024
e5bb578
finish content
attiasas May 12, 2024
d4c61af
remove debug
attiasas May 12, 2024
f8d146c
fix static
attiasas May 12, 2024
21195de
fix static
attiasas May 12, 2024
22f44ca
Merge remote-tracking branch 'upstream/dev' into add_summary_format
attiasas May 12, 2024
7ab7051
start CR
attiasas May 12, 2024
5501c94
Update core
attiasas May 12, 2024
a821bad
fix static
attiasas May 12, 2024
b90acf2
fix go sec
attiasas May 12, 2024
31978db
rename
attiasas May 12, 2024
c1dae32
update core
attiasas May 12, 2024
0ec0658
cleaning
attiasas May 12, 2024
476a04c
tests
attiasas May 12, 2024
85b42ac
finish tests
attiasas May 12, 2024
c356a97
fix tests
attiasas May 12, 2024
7f013ba
add test sca no applic status
attiasas May 12, 2024
016eafe
fix tests
attiasas May 12, 2024
1a34f0a
fix tests
attiasas May 12, 2024
6fae2c6
fix tests
attiasas May 12, 2024
eed6b93
fix test
attiasas May 15, 2024
edf4a30
update core
attiasas May 15, 2024
9a27815
update core
attiasas May 16, 2024
968f151
update core
attiasas May 16, 2024
e4debe2
fix tests
attiasas May 16, 2024
b2018bd
CR changes
attiasas May 19, 2024
a9f19a7
Update core
attiasas May 19, 2024
12f41ca
change title binary
attiasas May 19, 2024
919e3b3
GUI changes
attiasas May 19, 2024
a6abcc6
format
attiasas May 19, 2024
6b13f16
fix tests
attiasas May 19, 2024
00abe2f
update core
attiasas May 21, 2024
4a4d612
Merge remote-tracking branch 'upstream/dev' into add_summary_format
attiasas May 22, 2024
eabace1
update core
attiasas May 22, 2024
266ae4f
update core to dev
attiasas May 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions commands/audit/scarunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/jfrog/build-info-go/utils/pythonutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"os"
"time"

"github.com/jfrog/build-info-go/utils/pythonutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"

"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/common/project"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
Expand Down Expand Up @@ -58,9 +59,9 @@ func runScaScan(params *AuditParams, results *xrayutils.Results) (err error) {
}()
for _, scan := range scans {
// Run the scan
log.Info("Running SCA scan for", scan.Technology, "vulnerable dependencies in", scan.WorkingDirectory, "directory...")
log.Info("Running SCA scan for", scan.Technology, "vulnerable dependencies in", scan.Target, "directory...")
if wdScanErr := executeScaScan(serverDetails, params, scan); wdScanErr != nil {
err = errors.Join(err, fmt.Errorf("audit command in '%s' failed:\n%s", scan.WorkingDirectory, wdScanErr.Error()))
err = errors.Join(err, fmt.Errorf("audit command in '%s' failed:\n%s", scan.Target, wdScanErr.Error()))
continue
}
// Add the scan to the results
Expand All @@ -87,11 +88,11 @@ func getScaScansToPreform(params *AuditParams) (scansToPreform []*xrayutils.ScaS
}
if len(workingDirs) == 0 {
// Requested technology (from params) descriptors/indicators was not found, scan only requested directory for this technology.
scansToPreform = append(scansToPreform, &xrayutils.ScaScanResult{WorkingDirectory: requestedDirectory, Technology: tech})
scansToPreform = append(scansToPreform, &xrayutils.ScaScanResult{Target: requestedDirectory, Technology: tech})
}
for workingDir, descriptors := range workingDirs {
// Add scan for each detected working directory.
scansToPreform = append(scansToPreform, &xrayutils.ScaScanResult{WorkingDirectory: workingDir, Technology: tech, Descriptors: descriptors})
scansToPreform = append(scansToPreform, &xrayutils.ScaScanResult{Target: workingDir, Technology: tech, Descriptors: descriptors})
}
}
}
Expand All @@ -110,7 +111,7 @@ func getRequestedDescriptors(params *AuditParams) map[coreutils.Technology][]str
// This method will change the working directory to the scan's working directory.
func executeScaScan(serverDetails *config.ServerDetails, params *AuditParams, scan *xrayutils.ScaScanResult) (err error) {
// Get the dependency tree for the technology in the working directory.
if err = os.Chdir(scan.WorkingDirectory); err != nil {
if err = os.Chdir(scan.Target); err != nil {
return errorutils.CheckError(err)
}
treeResult, techErr := GetTechDependencyTree(params.AuditBasicParams, scan.Technology)
Expand Down
56 changes: 28 additions & 28 deletions commands/audit/scarunner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,23 +137,23 @@ func TestGetScaScansToPreform(t *testing.T) {
},
expected: []*xrayutils.ScaScanResult{
{
Technology: coreutils.Maven,
WorkingDirectory: filepath.Join(dir, "dir", "maven"),
Technology: coreutils.Maven,
Target: filepath.Join(dir, "dir", "maven"),
Descriptors: []string{
filepath.Join(dir, "dir", "maven", "pom.xml"),
filepath.Join(dir, "dir", "maven", "maven-sub", "pom.xml"),
filepath.Join(dir, "dir", "maven", "maven-sub2", "pom.xml"),
},
},
{
Technology: coreutils.Npm,
WorkingDirectory: filepath.Join(dir, "dir", "npm"),
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
Technology: coreutils.Npm,
Target: filepath.Join(dir, "dir", "npm"),
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
},
{
Technology: coreutils.Go,
WorkingDirectory: filepath.Join(dir, "dir", "go"),
Descriptors: []string{filepath.Join(dir, "dir", "go", "go.mod")},
Technology: coreutils.Go,
Target: filepath.Join(dir, "dir", "go"),
Descriptors: []string{filepath.Join(dir, "dir", "go", "go.mod")},
},
},
},
Expand All @@ -167,43 +167,43 @@ func TestGetScaScansToPreform(t *testing.T) {
},
expected: []*xrayutils.ScaScanResult{
{
Technology: coreutils.Maven,
WorkingDirectory: filepath.Join(dir, "dir", "maven"),
Technology: coreutils.Maven,
Target: filepath.Join(dir, "dir", "maven"),
Descriptors: []string{
filepath.Join(dir, "dir", "maven", "pom.xml"),
filepath.Join(dir, "dir", "maven", "maven-sub", "pom.xml"),
filepath.Join(dir, "dir", "maven", "maven-sub2", "pom.xml"),
},
},
{
Technology: coreutils.Npm,
WorkingDirectory: filepath.Join(dir, "dir", "npm"),
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
Technology: coreutils.Npm,
Target: filepath.Join(dir, "dir", "npm"),
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
},
{
Technology: coreutils.Go,
WorkingDirectory: filepath.Join(dir, "dir", "go"),
Descriptors: []string{filepath.Join(dir, "dir", "go", "go.mod")},
Technology: coreutils.Go,
Target: filepath.Join(dir, "dir", "go"),
Descriptors: []string{filepath.Join(dir, "dir", "go", "go.mod")},
},
{
Technology: coreutils.Yarn,
WorkingDirectory: filepath.Join(dir, "yarn"),
Descriptors: []string{filepath.Join(dir, "yarn", "package.json")},
Technology: coreutils.Yarn,
Target: filepath.Join(dir, "yarn"),
Descriptors: []string{filepath.Join(dir, "yarn", "package.json")},
},
{
Technology: coreutils.Pip,
WorkingDirectory: filepath.Join(dir, "yarn", "Pip"),
Descriptors: []string{filepath.Join(dir, "yarn", "Pip", "requirements.txt")},
Technology: coreutils.Pip,
Target: filepath.Join(dir, "yarn", "Pip"),
Descriptors: []string{filepath.Join(dir, "yarn", "Pip", "requirements.txt")},
},
{
Technology: coreutils.Pipenv,
WorkingDirectory: filepath.Join(dir, "yarn", "Pipenv"),
Descriptors: []string{filepath.Join(dir, "yarn", "Pipenv", "Pipfile")},
Technology: coreutils.Pipenv,
Target: filepath.Join(dir, "yarn", "Pipenv"),
Descriptors: []string{filepath.Join(dir, "yarn", "Pipenv", "Pipfile")},
},
{
Technology: coreutils.Nuget,
WorkingDirectory: filepath.Join(dir, "Nuget"),
Descriptors: []string{filepath.Join(dir, "Nuget", "project.sln"), filepath.Join(dir, "Nuget", "Nuget-sub", "project.csproj")},
Technology: coreutils.Nuget,
Target: filepath.Join(dir, "Nuget"),
Descriptors: []string{filepath.Join(dir, "Nuget", "project.sln"), filepath.Join(dir, "Nuget", "Nuget-sub", "project.csproj")},
},
},
},
Expand Down
8 changes: 6 additions & 2 deletions commands/scan/buildscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package scan

import (
"errors"
"fmt"

"github.com/jfrog/jfrog-cli-core/v2/common/build"
outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format"
Expand Down Expand Up @@ -130,7 +131,7 @@ func (bsc *BuildScanCommand) runBuildScanAndPrintResults(xrayManager *xray.XrayS

scanResults := xrutils.NewAuditResults()
scanResults.XrayVersion = xrayVersion
scanResults.ScaResults = []xrutils.ScaScanResult{{XrayResults: scanResponse}}
scanResults.ScaResults = []xrutils.ScaScanResult{{Target: fmt.Sprintf("%s (%s)", params.BuildName, params.BuildNumber), XrayResults: scanResponse}}

resultsPrinter := xrutils.NewResultsWriter(scanResults).
SetOutputFormat(bsc.outputFormat).
Expand All @@ -143,7 +144,9 @@ func (bsc *BuildScanCommand) runBuildScanAndPrintResults(xrayManager *xray.XrayS

if bsc.outputFormat != outputFormat.Table {
// Print the violations and/or vulnerabilities as part of one JSON.
err = resultsPrinter.PrintScanResults()
if err = resultsPrinter.PrintScanResults(); err != nil {
return
}
} else {
// Print two different tables for violations and vulnerabilities (if needed)

Expand All @@ -160,6 +163,7 @@ func (bsc *BuildScanCommand) runBuildScanAndPrintResults(xrayManager *xray.XrayS
}
}
}
err = utils.RecordSecurityCommandOutput(utils.ScanCommandSummaryResult{Results: scanResults.GetSummary(), Section: utils.Build})
return
}

Expand Down
26 changes: 18 additions & 8 deletions commands/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ import (
type FileContext func(string) parallel.TaskFunc
type indexFileHandlerFunc func(file string)

type ScanInfo struct {
Target string
Result *services.ScanResponse
}

const (
BypassArchiveLimitsMinXrayVersion = "3.59.0"
indexingCommand = "graph"
Expand Down Expand Up @@ -213,7 +218,7 @@ func (scanCmd *ScanCommand) Run() (err error) {
}

// resultsArr is a two-dimensional array. Each array in it contains a list of ScanResponses that were requested and collected by a specific thread.
resultsArr := make([][]*services.ScanResponse, threads)
resultsArr := make([][]*ScanInfo, threads)
fileProducerConsumer := parallel.NewRunner(scanCmd.threads, 20000, false)
fileProducerErrors := make([][]formats.SimpleJsonError, threads)
indexedFileProducerConsumer := parallel.NewRunner(scanCmd.threads, 20000, false)
Expand All @@ -225,10 +230,10 @@ func (scanCmd *ScanCommand) Run() (err error) {
scanCmd.performScanTasks(fileProducerConsumer, indexedFileProducerConsumer)

// Handle results
flatResults := []services.ScanResponse{}
flatResults := []xrutils.ScaScanResult{}
for _, arr := range resultsArr {
for _, res := range arr {
flatResults = append(flatResults, *res)
flatResults = append(flatResults, xrutils.ScaScanResult{Target: res.Target, XrayResults: []services.ScanResponse{*res.Result}})
}
}
if scanCmd.progress != nil {
Expand All @@ -248,7 +253,7 @@ func (scanCmd *ScanCommand) Run() (err error) {

scanResults := xrutils.NewAuditResults()
scanResults.XrayVersion = xrayVersion
scanResults.ScaResults = []xrutils.ScaScanResult{{XrayResults: flatResults}}
scanResults.ScaResults = flatResults

if err = xrutils.NewResultsWriter(scanResults).
SetOutputFormat(scanCmd.outputFormat).
Expand All @@ -264,10 +269,15 @@ func (scanCmd *ScanCommand) Run() (err error) {
if err != nil {
return err
}

if err = utils.RecordSecurityCommandOutput(utils.ScanCommandSummaryResult{Results: scanResults.GetSummary(), Section: utils.Binary}); err != nil {
return err
}

// If includeVulnerabilities is false it means that context was provided, so we need to check for build violations.
// If user provided --fail=false, don't fail the build.
if scanCmd.fail && !scanCmd.includeVulnerabilities {
if xrutils.CheckIfFailBuild(flatResults) {
if xrutils.CheckIfFailBuild(scanResults.GetScaScansXrayResults()) {
return xrutils.NewFailBuildError()
}
}
Expand All @@ -286,7 +296,7 @@ func (scanCmd *ScanCommand) CommandName() string {
return "xr_scan"
}

func (scanCmd *ScanCommand) prepareScanTasks(fileProducer, indexedFileProducer parallel.Runner, resultsArr [][]*services.ScanResponse, fileErrors, indexedFileErrors [][]formats.SimpleJsonError, fileCollectingErrorsQueue *clientutils.ErrorsQueue, xrayVersion string) {
func (scanCmd *ScanCommand) prepareScanTasks(fileProducer, indexedFileProducer parallel.Runner, resultsArr [][]*ScanInfo, fileErrors, indexedFileErrors [][]formats.SimpleJsonError, fileCollectingErrorsQueue *clientutils.ErrorsQueue, xrayVersion string) {
go func() {
defer fileProducer.Done()
// Iterate over file-spec groups and produce indexing tasks.
Expand All @@ -305,7 +315,7 @@ func (scanCmd *ScanCommand) prepareScanTasks(fileProducer, indexedFileProducer p
}()
}

func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, indexedFileProducer parallel.Runner, resultsArr [][]*services.ScanResponse, fileErrors, indexedFileErrors [][]formats.SimpleJsonError, xrayVersion string) FileContext {
func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, indexedFileProducer parallel.Runner, resultsArr [][]*ScanInfo, fileErrors, indexedFileErrors [][]formats.SimpleJsonError, xrayVersion string) FileContext {
return func(filePath string) parallel.TaskFunc {
return func(threadId int) (err error) {
logMsgPrefix := clientutils.GetLogMsgPrefix(threadId, false)
Expand Down Expand Up @@ -355,7 +365,7 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, indexedFil
indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()})
return
}
resultsArr[threadId] = append(resultsArr[threadId], scanResults)
resultsArr[threadId] = append(resultsArr[threadId], &ScanInfo{Target: filePath, Result: scanResults})
return
}

Expand Down
112 changes: 112 additions & 0 deletions formats/summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package formats

type SummaryResults struct {
Scans []ScanSummaryResult `json:"scans"`
}

func (sr SummaryResults) GetTotalIssueCount() (total int) {
for _, scan := range sr.Scans {
total += scan.GetTotalIssueCount()
}
return
}

type ScanSummaryResult struct {
Target string `json:"target,omitempty"`
ScaScanResults *ScaSummaryCount `json:"sca,omitempty"`
IacScanResults *SummaryCount `json:"iac,omitempty"`
SecretsScanResults *SummaryCount `json:"secrets,omitempty"`
SastScanResults *SummaryCount `json:"sast,omitempty"`
}

type SummarySubScanType string

const (
ScaScan SummarySubScanType = "SCA"
IacScan SummarySubScanType = "IAC"
SecretsScan SummarySubScanType = "Secrets"
SastScan SummarySubScanType = "SAST"
)

// Severity -> Count
type SummaryCount map[string]int

func (sc SummaryCount) GetTotal() int {
total := 0
for _, count := range sc {
total += count
}
return total
}

// Severity -> Applicable status -> Count
type ScaSummaryCount map[string]SummaryCount

func (sc ScaSummaryCount) GetTotal() (total int) {
for _, count := range sc {
total += count.GetTotal()
}
return
}

func (sc ScaSummaryCount) GetSeverityCountsWithoutStatus() (severityCounts SummaryCount) {
severityCounts = SummaryCount{}
for severity, statusCounts := range sc {
for _, count := range statusCounts {
severityCounts[severity] += count
}
}
return
}

func (s *ScanSummaryResult) HasIssues() bool {
return s.GetTotalIssueCount() > 0
}

func (s *ScanSummaryResult) GetTotalIssueCount() (total int) {
if s.ScaScanResults != nil {
total += s.ScaScanResults.GetTotal()
}
if s.IacScanResults != nil {
total += s.IacScanResults.GetTotal()
}
if s.SecretsScanResults != nil {
total += s.SecretsScanResults.GetTotal()
}
if s.SastScanResults != nil {
total += s.SastScanResults.GetTotal()
}
return
}

func (s *ScanSummaryResult) GetSubScansWithIssues() []SummarySubScanType {
subScans := []SummarySubScanType{}
if s.SecretsScanResults != nil && s.SecretsScanResults.GetTotal() > 0 {
subScans = append(subScans, SecretsScan)
}
if s.SastScanResults != nil && s.SastScanResults.GetTotal() > 0 {
subScans = append(subScans, SastScan)
}
if s.IacScanResults != nil && s.IacScanResults.GetTotal() > 0 {
subScans = append(subScans, IacScan)
}
// Must be last for element to also display contextual-analysis details
if s.ScaScanResults != nil && s.ScaScanResults.GetTotal() > 0 {
subScans = append(subScans, ScaScan)
}
return subScans
}

func (s *ScanSummaryResult) GetSubScanTotalIssueCount(subScanType SummarySubScanType) (count int) {
switch subScanType {
case ScaScan:
count = s.ScaScanResults.GetTotal()
case IacScan:
count = s.IacScanResults.GetTotal()
case SecretsScan:
count = s.SecretsScanResults.GetTotal()
case SastScan:
count = s.SastScanResults.GetTotal()
}
return
}
Loading
Loading