mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
feat(cve): better distinguish max severity on an image (#918)
Values returned now by GetCVESummaryForImage // not scannable / error during scan - max severity "" - cve count 0 - Errors // scannable no issues found - max severity "NONE" - cve count 0 - no Errors // scannable issues found - max severity from Scanner - cve count >0 - no Errors Before this change the max severity in case #1 and #2 was "UNKNOWN" which is also possible value for case #3. To better distinguish them return different max severities. This feature would be consumed by the UI. Signed-off-by: Andrei Aaron <andaaron@cisco.com>
This commit is contained in:
parent
1d9c88c313
commit
92afd86cbb
2 changed files with 77 additions and 5 deletions
|
@ -177,9 +177,13 @@ func (cveinfo BaseCveInfo) GetCVEListForImage(image string) (map[string]cvemodel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cveinfo BaseCveInfo) GetCVESummaryForImage(image string) (ImageCVESummary, error) {
|
func (cveinfo BaseCveInfo) GetCVESummaryForImage(image string) (ImageCVESummary, error) {
|
||||||
|
// There are several cases, expected returned values below:
|
||||||
|
// not scannable / error during scan - max severity "" - cve count 0 - Errors
|
||||||
|
// scannable no issues found - max severity "NONE" - cve count 0 - no Errors
|
||||||
|
// scannable issues found - max severity from Scanner - cve count >0 - no Errors
|
||||||
imageCVESummary := ImageCVESummary{
|
imageCVESummary := ImageCVESummary{
|
||||||
Count: 0,
|
Count: 0,
|
||||||
MaxSeverity: "UNKNOWN",
|
MaxSeverity: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidImage, err := cveinfo.Scanner.IsImageFormatScannable(image)
|
isValidImage, err := cveinfo.Scanner.IsImageFormatScannable(image)
|
||||||
|
@ -192,12 +196,20 @@ func (cveinfo BaseCveInfo) GetCVESummaryForImage(image string) (ImageCVESummary,
|
||||||
return imageCVESummary, err
|
return imageCVESummary, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imageCVESummary.Count = len(cveMap)
|
||||||
|
|
||||||
|
if imageCVESummary.Count == 0 {
|
||||||
|
imageCVESummary.MaxSeverity = "NONE"
|
||||||
|
|
||||||
|
return imageCVESummary, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCVESummary.MaxSeverity = "UNKNOWN"
|
||||||
for _, cve := range cveMap {
|
for _, cve := range cveMap {
|
||||||
if cveinfo.Scanner.CompareSeverities(imageCVESummary.MaxSeverity, cve.Severity) > 0 {
|
if cveinfo.Scanner.CompareSeverities(imageCVESummary.MaxSeverity, cve.Severity) > 0 {
|
||||||
imageCVESummary.MaxSeverity = cve.Severity
|
imageCVESummary.MaxSeverity = cve.Severity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imageCVESummary.Count = len(cveMap)
|
|
||||||
|
|
||||||
return imageCVESummary, nil
|
return imageCVESummary, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -829,6 +829,20 @@ func TestCVEStruct(t *testing.T) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Image with no CVEs
|
||||||
|
if repo == "repo4" { //nolint: goconst
|
||||||
|
return []ispec.Descriptor{
|
||||||
|
{
|
||||||
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
Size: int64(0),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ispec.AnnotationRefName: "1.0.0",
|
||||||
|
},
|
||||||
|
Digest: godigest.FromString("abc"),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// By default the image is not found
|
// By default the image is not found
|
||||||
return nil, errors.ErrRepoNotFound
|
return nil, errors.ErrRepoNotFound
|
||||||
},
|
},
|
||||||
|
@ -870,6 +884,17 @@ func TestCVEStruct(t *testing.T) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Image with no vulnerabilities, repo3 is for tests on missing images
|
||||||
|
if repo == "repo4" { //nolint: goconst
|
||||||
|
return []common.TagInfo{
|
||||||
|
{
|
||||||
|
Name: "1.0.0",
|
||||||
|
Digest: godigest.FromString("abc"),
|
||||||
|
Timestamp: time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// By default do not return any tags
|
// By default do not return any tags
|
||||||
return []common.TagInfo{}, errors.ErrRepoNotFound
|
return []common.TagInfo{}, errors.ErrRepoNotFound
|
||||||
},
|
},
|
||||||
|
@ -900,6 +925,19 @@ func TestCVEStruct(t *testing.T) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Image with no CVEs
|
||||||
|
if imageDir == "repo4" { //nolint: goconst
|
||||||
|
return ispec.Manifest{
|
||||||
|
Layers: []ispec.Descriptor{
|
||||||
|
{
|
||||||
|
MediaType: string(ispec.MediaTypeImageLayer),
|
||||||
|
Size: 0,
|
||||||
|
Digest: godigest.Digest(""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
return ispec.Manifest{}, errors.ErrBlobNotFound
|
return ispec.Manifest{}, errors.ErrBlobNotFound
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1054,13 +1092,19 @@ func TestCVEStruct(t *testing.T) {
|
||||||
cveSummary, err = cveInfo.GetCVESummaryForImage("repo2:1.0.0")
|
cveSummary, err = cveInfo.GetCVESummaryForImage("repo2:1.0.0")
|
||||||
So(err, ShouldEqual, errors.ErrScanNotSupported)
|
So(err, ShouldEqual, errors.ErrScanNotSupported)
|
||||||
So(cveSummary.Count, ShouldEqual, 0)
|
So(cveSummary.Count, ShouldEqual, 0)
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "UNKNOWN")
|
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
||||||
|
|
||||||
// Image is not found
|
// Image is not found
|
||||||
cveSummary, err = cveInfo.GetCVESummaryForImage("repo3:1.0.0")
|
cveSummary, err = cveInfo.GetCVESummaryForImage("repo3:1.0.0")
|
||||||
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
||||||
So(cveSummary.Count, ShouldEqual, 0)
|
So(cveSummary.Count, ShouldEqual, 0)
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "UNKNOWN")
|
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
||||||
|
|
||||||
|
// Image has no vulnerabilities
|
||||||
|
cveSummary, err = cveInfo.GetCVESummaryForImage("repo4:1.0.0")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(cveSummary.Count, ShouldEqual, 0)
|
||||||
|
So(cveSummary.MaxSeverity, ShouldEqual, "NONE")
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Test GetCVEListForImage", func() {
|
Convey("Test GetCVEListForImage", func() {
|
||||||
|
@ -1104,6 +1148,11 @@ func TestCVEStruct(t *testing.T) {
|
||||||
cveMap, err = cveInfo.GetCVEListForImage("repo3:1.0.0")
|
cveMap, err = cveInfo.GetCVEListForImage("repo3:1.0.0")
|
||||||
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
||||||
So(len(cveMap), ShouldEqual, 0)
|
So(len(cveMap), ShouldEqual, 0)
|
||||||
|
|
||||||
|
// Image has no vulnerabilities
|
||||||
|
cveMap, err = cveInfo.GetCVEListForImage("repo4:1.0.0")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(len(cveMap), ShouldEqual, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Test GetImageListWithCVEFixed", func() {
|
Convey("Test GetImageListWithCVEFixed", func() {
|
||||||
|
@ -1139,6 +1188,12 @@ func TestCVEStruct(t *testing.T) {
|
||||||
tagList, err = cveInfo.GetImageListWithCVEFixed("repo3", "CVE101")
|
tagList, err = cveInfo.GetImageListWithCVEFixed("repo3", "CVE101")
|
||||||
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
||||||
So(len(tagList), ShouldEqual, 0)
|
So(len(tagList), ShouldEqual, 0)
|
||||||
|
|
||||||
|
// Image has no vulnerabilities
|
||||||
|
tagList, err = cveInfo.GetImageListWithCVEFixed("repo4", "CVE101")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(len(tagList), ShouldEqual, 1)
|
||||||
|
So(tagList[0].Name, ShouldEqual, "1.0.0")
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Test GetImageListForCVE", func() {
|
Convey("Test GetImageListForCVE", func() {
|
||||||
|
@ -1175,6 +1230,11 @@ func TestCVEStruct(t *testing.T) {
|
||||||
imageInfoByCveList, err = cveInfo.GetImageListForCVE("repo3", "CVE101")
|
imageInfoByCveList, err = cveInfo.GetImageListForCVE("repo3", "CVE101")
|
||||||
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
||||||
So(len(imageInfoByCveList), ShouldEqual, 0)
|
So(len(imageInfoByCveList), ShouldEqual, 0)
|
||||||
|
|
||||||
|
// Image/repo is not vulnerable
|
||||||
|
imageInfoByCveList, err = cveInfo.GetImageListForCVE("repo4", "CVE101")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(len(imageInfoByCveList), ShouldEqual, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Test errors while scanning", func() {
|
Convey("Test errors while scanning", func() {
|
||||||
|
@ -1190,7 +1250,7 @@ func TestCVEStruct(t *testing.T) {
|
||||||
cveSummary, err := cveInfo.GetCVESummaryForImage("repo1:0.1.0")
|
cveSummary, err := cveInfo.GetCVESummaryForImage("repo1:0.1.0")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(cveSummary.Count, ShouldEqual, 0)
|
So(cveSummary.Count, ShouldEqual, 0)
|
||||||
So(cveSummary.MaxSeverity, ShouldEqual, "UNKNOWN")
|
So(cveSummary.MaxSeverity, ShouldEqual, "")
|
||||||
|
|
||||||
cveMap, err := cveInfo.GetCVEListForImage("repo1:0.1.0")
|
cveMap, err := cveInfo.GetCVEListForImage("repo1:0.1.0")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
|
|
Loading…
Reference in a new issue