Skip to content

Commit 3960d51

Browse files
feat(gql): add new query for diff of cves for 2 images
Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
1 parent 4e33c17 commit 3960d51

File tree

11 files changed

+1986
-64
lines changed

11 files changed

+1986
-64
lines changed

errors/errors.go

+2
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,6 @@ var (
168168
ErrAPINotSupported = errors.New("registry at the given address doesn't implement the correct API")
169169
ErrURLNotFound = errors.New("url not found")
170170
ErrInvalidSearchQuery = errors.New("invalid search query")
171+
ErrImageNotFound = errors.New("image not found")
172+
ErrAmbiguousInput = errors.New("input is not specific enough")
171173
)

pkg/extensions/search/cve/cve.go

+104-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import (
2121
type CveInfo interface {
2222
GetImageListForCVE(ctx context.Context, repo, cveID string) ([]cvemodel.TagInfo, error)
2323
GetImageListWithCVEFixed(ctx context.Context, repo, cveID string) ([]cvemodel.TagInfo, error)
24-
GetCVEListForImage(ctx context.Context, repo, tag string, searchedCVE string, excludedCVE string,
24+
GetCVEListForImage(ctx context.Context, repo, tag string, searchedCVE, excludedCVE string,
2525
pageinput cvemodel.PageInput) ([]cvemodel.CVE, cvemodel.ImageCVESummary, zcommon.PageInfo, error)
26+
GetCVEDiffListForImages(ctx context.Context, minuend, subtrahend, searchedCVE, excludedCVE string,
27+
pageInput cvemodel.PageInput) ([]cvemodel.CVE, cvemodel.ImageCVESummary, zcommon.PageInfo, error)
2628
GetCVESummaryForImageMedia(ctx context.Context, repo, digestStr, mediaType string) (cvemodel.ImageCVESummary, error)
2729
}
2830

@@ -329,7 +331,21 @@ func getConfigAndDigest(metaDB mTypes.MetaDB, manifestDigestStr string) (ispec.I
329331
return manifestData.Manifests[0].Config, manifestDigest, err
330332
}
331333

332-
func filterCVEList(cveMap map[string]cvemodel.CVE, searchedCVE, excludedCVE string, pageFinder *CvePageFinder) {
334+
func filterCVEMap(cveMap map[string]cvemodel.CVE, searchedCVE, excludedCVE string, pageFinder *CvePageFinder) {
335+
searchedCVE = strings.ToUpper(searchedCVE)
336+
337+
for _, cve := range cveMap {
338+
if excludedCVE != "" && cve.ContainsStr(excludedCVE) {
339+
continue
340+
}
341+
342+
if cve.ContainsStr(searchedCVE) {
343+
pageFinder.Add(cve)
344+
}
345+
}
346+
}
347+
348+
func filterCVEList(cveMap []cvemodel.CVE, searchedCVE, excludedCVE string, pageFinder *CvePageFinder) {
333349
searchedCVE = strings.ToUpper(searchedCVE)
334350

335351
for _, cve := range cveMap {
@@ -373,13 +389,98 @@ func (cveinfo BaseCveInfo) GetCVEListForImage(ctx context.Context, repo, ref str
373389
return []cvemodel.CVE{}, imageCVESummary, zcommon.PageInfo{}, err
374390
}
375391

376-
filterCVEList(cveMap, searchedCVE, excludedCVE, pageFinder)
392+
filterCVEMap(cveMap, searchedCVE, excludedCVE, pageFinder)
377393

378394
cveList, pageInfo := pageFinder.Page()
379395

380396
return cveList, imageCVESummary, pageInfo, nil
381397
}
382398

399+
func (cveinfo BaseCveInfo) GetCVEDiffListForImages(ctx context.Context, minuend, subtrahend, searchedCVE string,
400+
excludedCVE string, pageInput cvemodel.PageInput,
401+
) ([]cvemodel.CVE, cvemodel.ImageCVESummary, zcommon.PageInfo, error) {
402+
minuendRepo, minuendRef, _ := zcommon.GetImageDirAndReference(minuend)
403+
subtrahendRepo, subtrahendRef, _ := zcommon.GetImageDirAndReference(subtrahend)
404+
405+
// get the CVEs of image and comparedImage
406+
minuendCVEList, _, _, err := cveinfo.GetCVEListForImage(ctx, minuendRepo, minuendRef, searchedCVE, excludedCVE,
407+
cvemodel.PageInput{})
408+
if err != nil {
409+
return nil, cvemodel.ImageCVESummary{}, zcommon.PageInfo{}, err
410+
}
411+
412+
subtrahendCVEList, _, _, err := cveinfo.GetCVEListForImage(ctx, subtrahendRepo, subtrahendRef,
413+
searchedCVE, excludedCVE, cvemodel.PageInput{})
414+
if err != nil {
415+
return nil, cvemodel.ImageCVESummary{}, zcommon.PageInfo{}, err
416+
}
417+
418+
subtrahendCVEMap := map[string]cvemodel.CVE{}
419+
420+
for _, cve := range subtrahendCVEList {
421+
cve := cve
422+
subtrahendCVEMap[cve.ID] = cve
423+
}
424+
425+
var (
426+
count int
427+
unknownCount int
428+
lowCount int
429+
mediumCount int
430+
highCount int
431+
criticalCount int
432+
maxSeverity string
433+
434+
diffCVEs = []cvemodel.CVE{}
435+
)
436+
437+
for i := range minuendCVEList {
438+
if _, ok := subtrahendCVEMap[minuendCVEList[i].ID]; !ok {
439+
diffCVEs = append(diffCVEs, minuendCVEList[i])
440+
441+
switch minuendCVEList[i].Severity {
442+
case cvemodel.SeverityUnknown:
443+
unknownCount++
444+
case cvemodel.SeverityLow:
445+
lowCount++
446+
case cvemodel.SeverityMedium:
447+
mediumCount++
448+
case cvemodel.SeverityHigh:
449+
highCount++
450+
case cvemodel.SeverityCritical:
451+
criticalCount++
452+
}
453+
454+
if cvemodel.CompareSeverities(maxSeverity, minuendCVEList[i].Severity) > 0 {
455+
maxSeverity = minuendCVEList[i].Severity
456+
}
457+
}
458+
}
459+
460+
pageFinder, err := NewCvePageFinder(pageInput.Limit, pageInput.Offset, pageInput.SortBy)
461+
if err != nil {
462+
return nil, cvemodel.ImageCVESummary{}, zcommon.PageInfo{}, err
463+
}
464+
465+
filterCVEList(diffCVEs, "", "", pageFinder)
466+
467+
cveList, pageInfo := pageFinder.Page()
468+
469+
count = unknownCount + lowCount + mediumCount + highCount + criticalCount
470+
471+
diffCVESummary := cvemodel.ImageCVESummary{
472+
Count: count,
473+
UnknownCount: unknownCount,
474+
LowCount: lowCount,
475+
MediumCount: mediumCount,
476+
HighCount: highCount,
477+
CriticalCount: criticalCount,
478+
MaxSeverity: maxSeverity,
479+
}
480+
481+
return cveList, diffCVESummary, pageInfo, nil
482+
}
483+
383484
func (cveinfo BaseCveInfo) GetCVESummaryForImageMedia(ctx context.Context, repo, digestStr, mediaType string,
384485
) (cvemodel.ImageCVESummary, error) {
385486
// There are several cases, expected returned values below:

pkg/extensions/search/cve/cve_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,11 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
12771277
So(cveSummary.CriticalCount, ShouldEqual, 2)
12781278
So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL")
12791279

1280+
_, _, _, err = cveInfo.GetCVEDiffListForImages(ctx, "repo8:1.0.0", "repo1@"+image13Digest, "", "", pageInput)
1281+
So(err, ShouldBeNil)
1282+
_, _, _, err = cveInfo.GetCVEDiffListForImages(ctx, "repo8:1.0.0", "repo1:0.1.0", "", "", pageInput)
1283+
So(err, ShouldBeNil)
1284+
12801285
// Image is multiarch
12811286
cveList, cveSummary, pageInfo, err = cveInfo.GetCVEListForImage(ctx, repoMultiarch, "tagIndex", "", "", pageInput)
12821287
So(err, ShouldBeNil)
@@ -1625,6 +1630,35 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo
16251630

16261631
_, err = cveInfo.GetImageListForCVE(ctx, repoMultiarch, "CVE1")
16271632
So(err, ShouldBeNil)
1633+
1634+
cveInfo = cveinfo.BaseCveInfo{Log: log, Scanner: mocks.CveScannerMock{
1635+
IsImageFormatScannableFn: func(repo, reference string) (bool, error) {
1636+
return true, nil
1637+
},
1638+
ScanImageFn: func(ctx context.Context, image string) (map[string]cvemodel.CVE, error) {
1639+
return nil, zerr.ErrTypeAssertionFailed
1640+
},
1641+
}, MetaDB: metaDB}
1642+
_, _, _, err = cveInfo.GetCVEDiffListForImages(ctx, "repo8:1.0.0", "repo1:0.1.0", "", "", pageInput)
1643+
So(err, ShouldNotBeNil)
1644+
1645+
try := 0
1646+
cveInfo = cveinfo.BaseCveInfo{Log: log, Scanner: mocks.CveScannerMock{
1647+
IsImageFormatScannableFn: func(repo, reference string) (bool, error) {
1648+
return true, nil
1649+
},
1650+
ScanImageFn: func(ctx context.Context, image string) (map[string]cvemodel.CVE, error) {
1651+
if try == 1 {
1652+
return nil, zerr.ErrTypeAssertionFailed
1653+
}
1654+
1655+
try++
1656+
1657+
return make(map[string]cvemodel.CVE), nil
1658+
},
1659+
}, MetaDB: metaDB}
1660+
_, _, _, err = cveInfo.GetCVEDiffListForImages(ctx, "repo8:1.0.0", "repo6:0.1.0", "", "", pageInput)
1661+
So(err, ShouldNotBeNil)
16281662
})
16291663
}
16301664

0 commit comments

Comments
 (0)