Skip to content

Commit 4ebe3e2

Browse files
authored
fix(CxOne): Fix incremental scan count and full scan cycle handling (#5481)
1 parent 11e20cc commit 4ebe3e2

File tree

3 files changed

+80
-19
lines changed

3 files changed

+80
-19
lines changed

cmd/checkmarxOneExecuteScan.go

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,13 @@ func runStep(config checkmarxOneExecuteScanOptions, influx *checkmarxOneExecuteS
128128
}
129129
}
130130

131+
fullScanCycle, err := strconv.Atoi(cx1sh.config.FullScanCycle)
132+
if err != nil {
133+
log.SetErrorCategory(log.ErrorConfiguration)
134+
return fmt.Errorf("invalid configuration value for fullScanCycle %v, must be a positive int", cx1sh.config.FullScanCycle)
135+
}
131136
branch, isPR, baseBranch := cx1sh.GetScanBranch()
132-
scans, err := cx1sh.GetLastScans(10, branch)
137+
scans, err := cx1sh.GetLastScans(fullScanCycle+1, branch)
133138
if err != nil {
134139
log.Entry().WithError(err).Warnf("failed to get last 10 scans")
135140
}
@@ -153,7 +158,7 @@ func runStep(config checkmarxOneExecuteScanOptions, influx *checkmarxOneExecuteS
153158
}
154159
}
155160

156-
incremental, err := cx1sh.IncrementalOrFull(scans) // requires: scan list
161+
incremental, fullScanExists, contiguousIncrScansCurrentBranch, err := cx1sh.IncrementalOrFull(scans) // requires: scan list
157162
if err != nil {
158163
return fmt.Errorf("failed to determine incremental or full scan configuration: %s", err)
159164
}
@@ -174,24 +179,22 @@ func runStep(config checkmarxOneExecuteScanOptions, influx *checkmarxOneExecuteS
174179

175180
// TODO : The step structure should allow to enable different scanners: SAST, KICKS, SCA
176181
var scan *checkmarxOne.Scan
177-
// We search for a full scan in history:
178-
fullScanExists := false
179-
for _, histScan := range scans {
180-
isIncr, _ := histScan.IsIncremental()
181-
if isIncr == false {
182-
fullScanExists = true
183-
break
184-
}
185-
}
186182
// user requested an incremental scan on a branch, and the project has a Primary Branch set, not in PR context and no full scan on the branch
187183
if config.Incremental && !isPR && !fullScanExists && cx1sh.Project.MainBranch != "" && cx1sh.Project.MainBranch != branch {
188-
scansMainBranch, err := cx1sh.GetLastScans(10, cx1sh.Project.MainBranch)
184+
scansMainBranch, err := cx1sh.GetLastScans(fullScanCycle+1, cx1sh.Project.MainBranch)
189185
if err != nil {
190-
return fmt.Errorf("failed to determine incremental or full scan configuration: %s", err)
186+
return fmt.Errorf("failed to get scans from primary branch %v: %s", cx1sh.Project.MainBranch, err)
191187
}
192188
// We check if the main branch is eligible for an incremental scan
193-
incrementalMainBranch, err := cx1sh.IncrementalOrFull(scansMainBranch)
189+
incrementalMainBranch, _, contiguousIncrScansMainBranch, err := cx1sh.IncrementalOrFull(scansMainBranch)
190+
if err != nil {
191+
return fmt.Errorf("failed to determine incremental or full scan configuration: %s", err)
192+
}
194193
log.Entry().Debugf("Main branch %v incremental scan eligibility: %t", cx1sh.Project.MainBranch, incrementalMainBranch)
194+
if contiguousIncrScansMainBranch+contiguousIncrScansCurrentBranch+1 >= fullScanCycle { // contiguous incremental scans on main branch and current branch must not exceed fullScanCycle
195+
incrementalMainBranch = false
196+
}
197+
log.Entry().Debugf("Main branch + current branch incremental scan eligibility: %t", incrementalMainBranch)
195198
scan, err = cx1sh.CreateScanRequest(incrementalMainBranch, uploadLink, cx1sh.Project.MainBranch) // this will create a full scan on the current branch if the main branch is not eligible for an incremental scan
196199
} else if config.Incremental && isPR && len(baseBranch) > 0 && baseBranch != "n/a" { // running in a PR context, and we have a base branch for the incremental scan
197200
// in a PR context we always want to do an incremental scan
@@ -430,23 +433,46 @@ func (c *checkmarxOneExecuteScanHelper) GetLastScans(count int, branch string) (
430433
return scans, nil
431434
}
432435

433-
func (c *checkmarxOneExecuteScanHelper) IncrementalOrFull(scans []checkmarxOne.Scan) (bool, error) {
436+
func (c *checkmarxOneExecuteScanHelper) IncrementalOrFull(scans []checkmarxOne.Scan) (bool, bool, int, error) {
434437
incremental := c.config.Incremental
438+
fullScanExists := false
435439
fullScanCycle, err := strconv.Atoi(c.config.FullScanCycle)
436440
if err != nil {
437441
log.SetErrorCategory(log.ErrorConfiguration)
438-
return false, fmt.Errorf("invalid configuration value for fullScanCycle %v, must be a positive int", c.config.FullScanCycle)
442+
return false, false, 0, fmt.Errorf("invalid configuration value for fullScanCycle %v, must be a positive int", c.config.FullScanCycle)
439443
}
440444

441-
coherentIncrementalScans := c.getNumCoherentIncrementalScans(scans)
445+
if len(scans) == 0 {
446+
return false, false, 0, nil // no scans exist, so we need to do a full scan
447+
}
448+
449+
var scanIds []string
450+
for _, scan := range scans {
451+
scanIds = append(scanIds, scan.ScanID)
452+
}
453+
454+
scanMetadatas, err := c.sys.GetScanMetadatas(scanIds)
455+
if err != nil {
456+
return false, false, 0, errors.Wrapf(err, "failed to fetch metadata for scans")
457+
}
458+
459+
contiguousIncrementalScans := 0
460+
for _, scanMetadata := range scanMetadatas {
461+
if scanMetadata.IsIncremental {
462+
contiguousIncrementalScans++
463+
} else {
464+
fullScanExists = true
465+
break
466+
}
467+
}
442468

443469
if c.config.IsOptimizedAndScheduled {
444470
incremental = false
445-
} else if incremental && c.config.FullScansScheduled && fullScanCycle > 0 && (coherentIncrementalScans+1) >= fullScanCycle {
471+
} else if incremental && c.config.FullScansScheduled && fullScanCycle > 0 && (contiguousIncrementalScans+1) >= fullScanCycle {
446472
incremental = false
447473
}
448474

449-
return incremental, nil
475+
return incremental, fullScanExists, contiguousIncrementalScans, nil
450476
}
451477

452478
func (c *checkmarxOneExecuteScanHelper) ZipFiles() (*os.File, error) {
@@ -493,6 +519,11 @@ func (c *checkmarxOneExecuteScanHelper) GetScanBranch() (string, bool, string) {
493519
branch = fmt.Sprintf("PR%v-%v", cicdOrch.PullRequestConfig().Key, cicdOrch.PullRequestConfig().Branch)
494520
}
495521

522+
if branch == "" {
523+
branch = ".unknown"
524+
log.Entry().Info("No branch name found, using the cxone default '.unknown' as branch name")
525+
}
526+
496527
baseBranch := cicdOrch.PullRequestConfig().Base
497528
isPR := cicdOrch.IsPullRequest()
498529
log.Entry().Debugf("CxOne scan branch was automatically set to : %v", branch)

cmd/checkmarxOneExecuteScan_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ func (sys *checkmarxOneSystemMock) GetScanMetadata(scanID string) (checkmarxOne.
5454
return checkmarxOne.ScanMetadata{}, nil
5555
}
5656

57+
func (sys *checkmarxOneSystemMock) GetScanMetadatas(scanID []string) ([]checkmarxOne.ScanMetadata, error) {
58+
return []checkmarxOne.ScanMetadata{}, nil
59+
}
60+
5761
func (sys *checkmarxOneSystemMock) GetScanResults(scanID string, limit uint64) ([]checkmarxOne.ScanResult, error) {
5862
return []checkmarxOne.ScanResult{}, nil
5963
}

pkg/checkmarxone/checkmarxone.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ type ScanMetadata struct {
159159
PresetName string `json:"queryPreset"`
160160
}
161161

162+
type ScanMetadataList struct {
163+
TotalCount int
164+
Scans []ScanMetadata
165+
Missing []string
166+
}
167+
162168
type ScanResultData struct {
163169
QueryID uint64
164170
QueryName string
@@ -300,6 +306,7 @@ type System interface {
300306

301307
GetScan(scanID string) (Scan, error)
302308
GetScanMetadata(scanID string) (ScanMetadata, error)
309+
GetScanMetadatas(scanIDs []string) ([]ScanMetadata, error)
303310
GetScanResults(scanID string, limit uint64) ([]ScanResult, error)
304311
GetScanSummary(scanID string) (ScanSummary, error)
305312
GetResultsPredicates(SimilarityID int64, ProjectID string) ([]ResultsPredicates, error)
@@ -1116,6 +1123,25 @@ func (sys *SystemInstance) GetScan(scanID string) (Scan, error) {
11161123
return scan, nil
11171124
}
11181125

1126+
func (sys *SystemInstance) GetScanMetadatas(scanIDs []string) ([]ScanMetadata, error) {
1127+
params := url.Values{
1128+
"scan-ids": scanIDs,
1129+
}
1130+
var scanmetadatalistresp ScanMetadataList
1131+
var scans []ScanMetadata
1132+
1133+
data, err := sendRequest(sys, http.MethodGet, fmt.Sprintf("/sast-metadata?%v", params.Encode()), nil, http.Header{}, []int{})
1134+
if err != nil {
1135+
sys.logger.Errorf("Failed to fetch metadata for scans %s, error was: %s", fmt.Sprintf("%v", strings.Join(scanIDs, ",")), err)
1136+
return scans, errors.Wrapf(err, "failed to fetch metadata for scans")
1137+
}
1138+
1139+
json.Unmarshal(data, &scanmetadatalistresp)
1140+
scans = scanmetadatalistresp.Scans
1141+
return scans, nil
1142+
1143+
}
1144+
11191145
func (sys *SystemInstance) GetScanMetadata(scanID string) (ScanMetadata, error) {
11201146
var scanmeta ScanMetadata
11211147

0 commit comments

Comments
 (0)