mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
feat: include PackagePath data in CVEs for image queries (#2241)
Signed-off-by: Vishwas Rajashekar <vrajashe@cisco.com>
This commit is contained in:
parent
cc2eda0335
commit
0aa6bf0fff
13 changed files with 227 additions and 17 deletions
1
Makefile
1
Makefile
|
@ -230,6 +230,7 @@ $(TESTDATA): check-skopeo
|
||||||
skopeo --insecure-policy copy -q docker://public.ecr.aws/t0x7q1g8/centos:8 oci:${TESTDATA}/zot-cve-test:0.0.1; \
|
skopeo --insecure-policy copy -q docker://public.ecr.aws/t0x7q1g8/centos:8 oci:${TESTDATA}/zot-cve-test:0.0.1; \
|
||||||
skopeo --insecure-policy copy -q docker://ghcr.io/project-zot/test-images/java:0.0.1 oci:${TESTDATA}/zot-cve-java-test:0.0.1; \
|
skopeo --insecure-policy copy -q docker://ghcr.io/project-zot/test-images/java:0.0.1 oci:${TESTDATA}/zot-cve-java-test:0.0.1; \
|
||||||
skopeo --insecure-policy copy -q docker://ghcr.io/project-zot/test-images/alpine:3.17.3 oci:${TESTDATA}/alpine:3.17.3; \
|
skopeo --insecure-policy copy -q docker://ghcr.io/project-zot/test-images/alpine:3.17.3 oci:${TESTDATA}/alpine:3.17.3; \
|
||||||
|
skopeo --insecure-policy copy -q docker://ghcr.io/project-zot/test-images/spring-web:5.3.31 oci:${TESTDATA}/spring-web:5.3.31; \
|
||||||
chmod -R a=rwx ${TESTDATA}
|
chmod -R a=rwx ${TESTDATA}
|
||||||
ls -R -l ${TESTDATA}
|
ls -R -l ${TESTDATA}
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ func TestSearchCVECmd(t *testing.T) {
|
||||||
So(buff.String(), ShouldEqual, `{"Tag":"dummyImageName:tag","CVEList":`+
|
So(buff.String(), ShouldEqual, `{"Tag":"dummyImageName:tag","CVEList":`+
|
||||||
`[{"Id":"dummyCVEID","Severity":"HIGH","Title":"Title of that CVE",`+
|
`[{"Id":"dummyCVEID","Severity":"HIGH","Title":"Title of that CVE",`+
|
||||||
`"Description":"Description of the CVE","PackageList":[{"Name":"packagename",`+
|
`"Description":"Description of the CVE","PackageList":[{"Name":"packagename",`+
|
||||||
`"InstalledVersion":"installedver","FixedVersion":"fixedver"}]}],"Summary":`+
|
`"PackagePath":"","InstalledVersion":"installedver","FixedVersion":"fixedver"}]}],"Summary":`+
|
||||||
`{"maxSeverity":"HIGH","unknownCount":0,"lowCount":0,"mediumCount":0,"highCount":1,`+
|
`{"maxSeverity":"HIGH","unknownCount":0,"lowCount":0,"mediumCount":0,"highCount":1,`+
|
||||||
`"criticalCount":0,"count":1}}`+"\n")
|
`"criticalCount":0,"count":1}}`+"\n")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
@ -247,7 +247,7 @@ func TestSearchCVECmd(t *testing.T) {
|
||||||
str := space.ReplaceAllString(buff.String(), " ")
|
str := space.ReplaceAllString(buff.String(), " ")
|
||||||
So(strings.TrimSpace(str), ShouldEqual, `--- tag: dummyImageName:tag cvelist: - id: dummyCVEID`+
|
So(strings.TrimSpace(str), ShouldEqual, `--- tag: dummyImageName:tag cvelist: - id: dummyCVEID`+
|
||||||
` severity: HIGH title: Title of that CVE description: Description of the CVE packagelist: `+
|
` severity: HIGH title: Title of that CVE description: Description of the CVE packagelist: `+
|
||||||
`- name: packagename installedversion: installedver fixedversion: fixedver `+
|
`- name: packagename packagepath: "" installedversion: installedver fixedversion: fixedver `+
|
||||||
`summary: maxseverity: HIGH unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 1 criticalcount: 0 count: 1`)
|
`summary: maxseverity: HIGH unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 1 criticalcount: 0 count: 1`)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
})
|
})
|
||||||
|
|
|
@ -345,13 +345,33 @@ func TestSearchCVEForImageGQL(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ID: "test-cve-id2",
|
||||||
|
Description: "Test CVE ID 2",
|
||||||
|
Title: "Test CVE 2",
|
||||||
|
Severity: "HIGH",
|
||||||
|
PackageList: []packageList{
|
||||||
|
{
|
||||||
|
Name: "packagename",
|
||||||
|
PackagePath: "/usr/bin/dummy.jar",
|
||||||
|
FixedVersion: "fixedver",
|
||||||
|
InstalledVersion: "installedver",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "packagename",
|
||||||
|
PackagePath: "/usr/bin/dummy.gem",
|
||||||
|
FixedVersion: "fixedver",
|
||||||
|
InstalledVersion: "installedver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Summary: common.ImageVulnerabilitySummary{
|
Summary: common.ImageVulnerabilitySummary{
|
||||||
Count: 1,
|
Count: 2,
|
||||||
UnknownCount: 0,
|
UnknownCount: 0,
|
||||||
LowCount: 0,
|
LowCount: 0,
|
||||||
MediumCount: 0,
|
MediumCount: 0,
|
||||||
HighCount: 1,
|
HighCount: 2,
|
||||||
CriticalCount: 0,
|
CriticalCount: 0,
|
||||||
MaxSeverity: "HIGH",
|
MaxSeverity: "HIGH",
|
||||||
},
|
},
|
||||||
|
@ -363,14 +383,27 @@ func TestSearchCVEForImageGQL(t *testing.T) {
|
||||||
|
|
||||||
err := SearchCVEForImageGQL(searchConfig, "repo-test", "dummyCVEID")
|
err := SearchCVEForImageGQL(searchConfig, "repo-test", "dummyCVEID")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
bufferContent := buff.String()
|
||||||
|
bufferLines := strings.Split(bufferContent, "\n")
|
||||||
|
|
||||||
|
// Expected result - each row indicates a row of the table with reduced spaces
|
||||||
|
expected := []string{
|
||||||
|
"CRITICAL 0, HIGH 2, MEDIUM 0, LOW 0, UNKNOWN 0, TOTAL 2",
|
||||||
|
"",
|
||||||
|
"ID SEVERITY TITLE",
|
||||||
|
"dummyCVEID HIGH Title of that CVE",
|
||||||
|
"test-cve-id2 HIGH Test CVE 2",
|
||||||
|
}
|
||||||
|
|
||||||
space := regexp.MustCompile(`\s+`)
|
space := regexp.MustCompile(`\s+`)
|
||||||
str := space.ReplaceAllString(buff.String(), " ")
|
|
||||||
actual := strings.TrimSpace(str)
|
for lineIndex := 0; lineIndex < len(expected); lineIndex++ {
|
||||||
So(actual, ShouldContainSubstring, "CRITICAL 0, HIGH 1, MEDIUM 0, LOW 0, UNKNOWN 0, TOTAL 1")
|
line := space.ReplaceAllString(bufferLines[lineIndex], " ")
|
||||||
So(actual, ShouldContainSubstring, "dummyCVEID HIGH Title of that CVE")
|
So(line, ShouldEqualTrimSpace, expected[lineIndex])
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("SearchCVEForImageGQL", t, func() {
|
Convey("SearchCVEForImageGQL with injected error", t, func() {
|
||||||
buff := bytes.NewBufferString("")
|
buff := bytes.NewBufferString("")
|
||||||
searchConfig := getMockSearchConfig(buff, mockService{
|
searchConfig := getMockSearchConfig(buff, mockService{
|
||||||
getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||||
|
|
|
@ -308,7 +308,7 @@ func (service searchService) getCveByImageGQL(ctx context.Context, config Search
|
||||||
Tag
|
Tag
|
||||||
CVEList {
|
CVEList {
|
||||||
Id Title Severity Description
|
Id Title Severity Description
|
||||||
PackageList {Name InstalledVersion FixedVersion}
|
PackageList {Name PackagePath InstalledVersion FixedVersion}
|
||||||
}
|
}
|
||||||
Summary {
|
Summary {
|
||||||
Count UnknownCount LowCount MediumCount HighCount CriticalCount MaxSeverity
|
Count UnknownCount LowCount MediumCount HighCount CriticalCount MaxSeverity
|
||||||
|
@ -732,6 +732,7 @@ type tagListResp struct {
|
||||||
//nolint:tagliatelle // graphQL schema
|
//nolint:tagliatelle // graphQL schema
|
||||||
type packageList struct {
|
type packageList struct {
|
||||||
Name string `json:"Name"`
|
Name string `json:"Name"`
|
||||||
|
PackagePath string `json:"PackagePath"`
|
||||||
InstalledVersion string `json:"InstalledVersion"`
|
InstalledVersion string `json:"InstalledVersion"`
|
||||||
FixedVersion string `json:"FixedVersion"`
|
FixedVersion string `json:"FixedVersion"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,13 @@ func TestUtils(t *testing.T) {
|
||||||
PackageList: []cvemodel.Package{
|
PackageList: []cvemodel.Package{
|
||||||
{
|
{
|
||||||
Name: "NameTest",
|
Name: "NameTest",
|
||||||
|
PackagePath: "/usr/bin/artifacts/dummy.jar",
|
||||||
|
FixedVersion: "FixedVersionTest",
|
||||||
|
InstalledVersion: "InstalledVersionTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NameTest",
|
||||||
|
PackagePath: "/usr/local/artifacts/dummy.gem",
|
||||||
FixedVersion: "FixedVersionTest",
|
FixedVersion: "FixedVersionTest",
|
||||||
InstalledVersion: "InstalledVersionTest",
|
InstalledVersion: "InstalledVersionTest",
|
||||||
},
|
},
|
||||||
|
@ -34,6 +41,10 @@ func TestUtils(t *testing.T) {
|
||||||
So(cve.ContainsStr("NameTest"), ShouldBeTrue)
|
So(cve.ContainsStr("NameTest"), ShouldBeTrue)
|
||||||
So(cve.ContainsStr("FixedVersionTest"), ShouldBeTrue)
|
So(cve.ContainsStr("FixedVersionTest"), ShouldBeTrue)
|
||||||
So(cve.ContainsStr("InstalledVersionTest"), ShouldBeTrue)
|
So(cve.ContainsStr("InstalledVersionTest"), ShouldBeTrue)
|
||||||
|
So(cve.ContainsStr("/usr/bin/artifacts/dummy.jar"), ShouldBeTrue)
|
||||||
|
So(cve.ContainsStr("dummy.jar"), ShouldBeTrue)
|
||||||
|
So(cve.ContainsStr("/usr/local/artifacts/dummy.gem"), ShouldBeTrue)
|
||||||
|
So(cve.ContainsStr("dummy.gem"), ShouldBeTrue)
|
||||||
})
|
})
|
||||||
Convey("getConfigAndDigest", func() {
|
Convey("getConfigAndDigest", func() {
|
||||||
_, _, err := getConfigAndDigest(mocks.MetaDBMock{}, "bad-digest")
|
_, _, err := getConfigAndDigest(mocks.MetaDBMock{}, "bad-digest")
|
||||||
|
|
|
@ -39,13 +39,15 @@ func (cve *CVE) ContainsStr(str string) bool {
|
||||||
slices.ContainsFunc(cve.PackageList, func(pack Package) bool {
|
slices.ContainsFunc(cve.PackageList, func(pack Package) bool {
|
||||||
return strings.Contains(strings.ToUpper(pack.Name), str) ||
|
return strings.Contains(strings.ToUpper(pack.Name), str) ||
|
||||||
strings.Contains(strings.ToUpper(pack.FixedVersion), str) ||
|
strings.Contains(strings.ToUpper(pack.FixedVersion), str) ||
|
||||||
strings.Contains(strings.ToUpper(pack.InstalledVersion), str)
|
strings.Contains(strings.ToUpper(pack.InstalledVersion), str) ||
|
||||||
|
strings.Contains(strings.ToUpper(pack.PackagePath), str)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:tagliatelle // graphQL schema
|
//nolint:tagliatelle // graphQL schema
|
||||||
type Package struct {
|
type Package struct {
|
||||||
Name string `json:"Name"`
|
Name string `json:"Name"`
|
||||||
|
PackagePath string `json:"PackagePath"`
|
||||||
InstalledVersion string `json:"InstalledVersion"`
|
InstalledVersion string `json:"InstalledVersion"`
|
||||||
FixedVersion string `json:"FixedVersion"`
|
FixedVersion string `json:"FixedVersion"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,6 +394,13 @@ func (scanner Scanner) scanManifest(ctx context.Context, repo, digest string) (m
|
||||||
fixedVersion = "Not Specified"
|
fixedVersion = "Not Specified"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var packagePath string
|
||||||
|
if vulnerability.PkgPath != "" {
|
||||||
|
packagePath = vulnerability.PkgPath
|
||||||
|
} else {
|
||||||
|
packagePath = "Not Specified"
|
||||||
|
}
|
||||||
|
|
||||||
_, ok := cveidMap[vulnerability.VulnerabilityID]
|
_, ok := cveidMap[vulnerability.VulnerabilityID]
|
||||||
if ok {
|
if ok {
|
||||||
cveDetailStruct := cveidMap[vulnerability.VulnerabilityID]
|
cveDetailStruct := cveidMap[vulnerability.VulnerabilityID]
|
||||||
|
@ -404,6 +411,7 @@ func (scanner Scanner) scanManifest(ctx context.Context, repo, digest string) (m
|
||||||
pkgList,
|
pkgList,
|
||||||
cvemodel.Package{
|
cvemodel.Package{
|
||||||
Name: pkgName,
|
Name: pkgName,
|
||||||
|
PackagePath: packagePath,
|
||||||
InstalledVersion: installedVersion,
|
InstalledVersion: installedVersion,
|
||||||
FixedVersion: fixedVersion,
|
FixedVersion: fixedVersion,
|
||||||
},
|
},
|
||||||
|
@ -419,6 +427,7 @@ func (scanner Scanner) scanManifest(ctx context.Context, repo, digest string) (m
|
||||||
newPkgList,
|
newPkgList,
|
||||||
cvemodel.Package{
|
cvemodel.Package{
|
||||||
Name: pkgName,
|
Name: pkgName,
|
||||||
|
PackagePath: packagePath,
|
||||||
InstalledVersion: installedVersion,
|
InstalledVersion: installedVersion,
|
||||||
FixedVersion: fixedVersion,
|
FixedVersion: fixedVersion,
|
||||||
},
|
},
|
||||||
|
|
|
@ -206,6 +206,84 @@ func TestVulnerableLayer(t *testing.T) {
|
||||||
So(cveMap, ShouldContainKey, "CVE-2023-3817")
|
So(cveMap, ShouldContainKey, "CVE-2023-3817")
|
||||||
So(cveMap, ShouldContainKey, "CVE-2023-3446")
|
So(cveMap, ShouldContainKey, "CVE-2023-3446")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Convey("Vulnerable layer with vulnerability in language-specific file", t, func() {
|
||||||
|
vulnerableLayer, err := GetLayerWithLanguageFileVulnerability()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
created, err := time.Parse(time.RFC3339, "2024-02-15T09:56:01.500079786Z")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
config := ispec.Image{
|
||||||
|
Created: &created,
|
||||||
|
Platform: ispec.Platform{
|
||||||
|
Architecture: "amd64",
|
||||||
|
OS: "linux",
|
||||||
|
},
|
||||||
|
Config: ispec.ImageConfig{
|
||||||
|
Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
|
||||||
|
},
|
||||||
|
RootFS: ispec.RootFS{
|
||||||
|
Type: "layers",
|
||||||
|
DiffIDs: []godigest.Digest{"sha256:d789b0723f3e6e5064d612eb3c84071cc84a7cf7921d549642252c3295e5f937"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
img := CreateImageWith().
|
||||||
|
LayerBlobs([][]byte{vulnerableLayer}).
|
||||||
|
ImageConfig(config).
|
||||||
|
Build()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
log := log.NewLogger("debug", "")
|
||||||
|
imageStore := local.NewImageStore(tempDir, false, false,
|
||||||
|
log, monitoring.NewMetricsServer(false, log), nil, nil)
|
||||||
|
|
||||||
|
storeController := storage.StoreController{
|
||||||
|
DefaultStore: imageStore,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = WriteImageToFileSystem(img, "repo", img.DigestStr(), storeController)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
params := boltdb.DBParameters{
|
||||||
|
RootDir: tempDir,
|
||||||
|
}
|
||||||
|
boltDriver, err := boltdb.GetBoltDriver(params)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
metaDB, err := boltdb.New(boltDriver, log)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
err = meta.ParseStorage(metaDB, storeController, log)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
scanner := trivy.NewScanner(storeController, metaDB, "ghcr.io/project-zot/trivy-db",
|
||||||
|
"ghcr.io/aquasecurity/trivy-java-db", log)
|
||||||
|
|
||||||
|
err = scanner.UpdateDB(context.Background())
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
cveMap, err := scanner.ScanImage(context.Background(), "repo@"+img.DigestStr())
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
t.Logf("cveMap: %v", cveMap)
|
||||||
|
|
||||||
|
// As of Feb 15 2024, there is 1 CVE in this layer:
|
||||||
|
So(len(cveMap), ShouldBeGreaterThanOrEqualTo, 1)
|
||||||
|
So(cveMap, ShouldContainKey, "CVE-2016-1000027")
|
||||||
|
|
||||||
|
cveData := cveMap["CVE-2016-1000027"]
|
||||||
|
vulnerablePackages := cveData.PackageList
|
||||||
|
|
||||||
|
// There is only 1 vulnerable package in this layer
|
||||||
|
So(len(vulnerablePackages), ShouldEqual, 1)
|
||||||
|
vulnerableSpringWebPackage := vulnerablePackages[0]
|
||||||
|
So(vulnerableSpringWebPackage.Name, ShouldEqual, "org.springframework:spring-web")
|
||||||
|
So(vulnerableSpringWebPackage.InstalledVersion, ShouldEqual, "5.3.31")
|
||||||
|
So(vulnerableSpringWebPackage.FixedVersion, ShouldEqual, "6.0.0")
|
||||||
|
So(vulnerableSpringWebPackage.PackagePath, ShouldEqual, "usr/local/artifacts/spring-web-5.3.31.jar")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestScannerErrors(t *testing.T) {
|
func TestScannerErrors(t *testing.T) {
|
||||||
|
|
|
@ -145,6 +145,7 @@ type ComplexityRoot struct {
|
||||||
FixedVersion func(childComplexity int) int
|
FixedVersion func(childComplexity int) int
|
||||||
InstalledVersion func(childComplexity int) int
|
InstalledVersion func(childComplexity int) int
|
||||||
Name func(childComplexity int) int
|
Name func(childComplexity int) int
|
||||||
|
PackagePath func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
PageInfo struct {
|
PageInfo struct {
|
||||||
|
@ -737,6 +738,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||||
|
|
||||||
return e.complexity.PackageInfo.Name(childComplexity), true
|
return e.complexity.PackageInfo.Name(childComplexity), true
|
||||||
|
|
||||||
|
case "PackageInfo.PackagePath":
|
||||||
|
if e.complexity.PackageInfo.PackagePath == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.PackageInfo.PackagePath(childComplexity), true
|
||||||
|
|
||||||
case "PageInfo.ItemCount":
|
case "PageInfo.ItemCount":
|
||||||
if e.complexity.PageInfo.ItemCount == nil {
|
if e.complexity.PageInfo.ItemCount == nil {
|
||||||
break
|
break
|
||||||
|
@ -1275,6 +1283,10 @@ type PackageInfo {
|
||||||
"""
|
"""
|
||||||
Name: String
|
Name: String
|
||||||
"""
|
"""
|
||||||
|
Path where the vulnerable package is located
|
||||||
|
"""
|
||||||
|
PackagePath: String
|
||||||
|
"""
|
||||||
Current version of the package, typically affected by the CVE
|
Current version of the package, typically affected by the CVE
|
||||||
"""
|
"""
|
||||||
InstalledVersion: String
|
InstalledVersion: String
|
||||||
|
@ -2749,6 +2761,8 @@ func (ec *executionContext) fieldContext_CVE_PackageList(ctx context.Context, fi
|
||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "Name":
|
case "Name":
|
||||||
return ec.fieldContext_PackageInfo_Name(ctx, field)
|
return ec.fieldContext_PackageInfo_Name(ctx, field)
|
||||||
|
case "PackagePath":
|
||||||
|
return ec.fieldContext_PackageInfo_PackagePath(ctx, field)
|
||||||
case "InstalledVersion":
|
case "InstalledVersion":
|
||||||
return ec.fieldContext_PackageInfo_InstalledVersion(ctx, field)
|
return ec.fieldContext_PackageInfo_InstalledVersion(ctx, field)
|
||||||
case "FixedVersion":
|
case "FixedVersion":
|
||||||
|
@ -5431,6 +5445,47 @@ func (ec *executionContext) fieldContext_PackageInfo_Name(ctx context.Context, f
|
||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _PackageInfo_PackagePath(ctx context.Context, field graphql.CollectedField, obj *PackageInfo) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_PackageInfo_PackagePath(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.PackagePath, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(*string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_PackageInfo_PackagePath(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "PackageInfo",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type String does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _PackageInfo_InstalledVersion(ctx context.Context, field graphql.CollectedField, obj *PackageInfo) (ret graphql.Marshaler) {
|
func (ec *executionContext) _PackageInfo_InstalledVersion(ctx context.Context, field graphql.CollectedField, obj *PackageInfo) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_PackageInfo_InstalledVersion(ctx, field)
|
fc, err := ec.fieldContext_PackageInfo_InstalledVersion(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10318,6 +10373,8 @@ func (ec *executionContext) _PackageInfo(ctx context.Context, sel ast.SelectionS
|
||||||
out.Values[i] = graphql.MarshalString("PackageInfo")
|
out.Values[i] = graphql.MarshalString("PackageInfo")
|
||||||
case "Name":
|
case "Name":
|
||||||
out.Values[i] = ec._PackageInfo_Name(ctx, field, obj)
|
out.Values[i] = ec._PackageInfo_Name(ctx, field, obj)
|
||||||
|
case "PackagePath":
|
||||||
|
out.Values[i] = ec._PackageInfo_PackagePath(ctx, field, obj)
|
||||||
case "InstalledVersion":
|
case "InstalledVersion":
|
||||||
out.Values[i] = ec._PackageInfo_InstalledVersion(ctx, field, obj)
|
out.Values[i] = ec._PackageInfo_InstalledVersion(ctx, field, obj)
|
||||||
case "FixedVersion":
|
case "FixedVersion":
|
||||||
|
|
|
@ -209,6 +209,8 @@ type ManifestSummary struct {
|
||||||
type PackageInfo struct {
|
type PackageInfo struct {
|
||||||
// Name of the package affected by a CVE
|
// Name of the package affected by a CVE
|
||||||
Name *string `json:"Name,omitempty"`
|
Name *string `json:"Name,omitempty"`
|
||||||
|
// Path where the vulnerable package is located
|
||||||
|
PackagePath *string `json:"PackagePath,omitempty"`
|
||||||
// Current version of the package, typically affected by the CVE
|
// Current version of the package, typically affected by the CVE
|
||||||
InstalledVersion *string `json:"InstalledVersion,omitempty"`
|
InstalledVersion *string `json:"InstalledVersion,omitempty"`
|
||||||
// Minimum version of the package in which the CVE is fixed
|
// Minimum version of the package in which the CVE is fixed
|
||||||
|
|
|
@ -241,6 +241,7 @@ func getCVEListForImage(
|
||||||
pkgList = append(pkgList,
|
pkgList = append(pkgList,
|
||||||
&gql_generated.PackageInfo{
|
&gql_generated.PackageInfo{
|
||||||
Name: &pkg.Name,
|
Name: &pkg.Name,
|
||||||
|
PackagePath: &pkg.PackagePath,
|
||||||
InstalledVersion: &pkg.InstalledVersion,
|
InstalledVersion: &pkg.InstalledVersion,
|
||||||
FixedVersion: &pkg.FixedVersion,
|
FixedVersion: &pkg.FixedVersion,
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,6 +73,10 @@ type PackageInfo {
|
||||||
"""
|
"""
|
||||||
Name: String
|
Name: String
|
||||||
"""
|
"""
|
||||||
|
Path where the vulnerable package is located
|
||||||
|
"""
|
||||||
|
PackagePath: String
|
||||||
|
"""
|
||||||
Current version of the package, typically affected by the CVE
|
Current version of the package, typically affected by the CVE
|
||||||
"""
|
"""
|
||||||
InstalledVersion: String
|
InstalledVersion: String
|
||||||
|
|
|
@ -29,23 +29,34 @@ func GetLayerWithVulnerability() ([]byte, error) {
|
||||||
if vulnerableLayer != nil {
|
if vulnerableLayer != nil {
|
||||||
return vulnerableLayer, nil
|
return vulnerableLayer, nil
|
||||||
}
|
}
|
||||||
|
// this is the path of the blob relative to the root of the zot folder
|
||||||
|
vulnBlobPath := "test/data/alpine/blobs/sha256/f56be85fc22e46face30e2c3de3f7fe7c15f8fd7c4e5add29d7f64b87abdaa09"
|
||||||
|
vulnerableLayer, err := GetLayerRelativeToProjectRoot(vulnBlobPath)
|
||||||
|
|
||||||
|
return vulnerableLayer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLayerWithLanguageFileVulnerability() ([]byte, error) {
|
||||||
|
vulnBlobPath := "test/data/spring-web/blobs/sha256/506c47a6827e325a63d4b38c7ce656e07d5e98a09d748ec7ac989a45af7d6567"
|
||||||
|
vulnerableLayerWithLanguageFile, err := GetLayerRelativeToProjectRoot(vulnBlobPath)
|
||||||
|
|
||||||
|
return vulnerableLayerWithLanguageFile, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLayerRelativeToProjectRoot(pathToLayerBlob string) ([]byte, error) {
|
||||||
projectRootDir, err := tcommon.GetProjectRootDir()
|
projectRootDir, err := tcommon.GetProjectRootDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the path of the blob relative to the root of the zot folder
|
absoluteBlobPath, _ := filepath.Abs(filepath.Join(projectRootDir, pathToLayerBlob))
|
||||||
vulnBlobPath := "test/data/alpine/blobs/sha256/f56be85fc22e46face30e2c3de3f7fe7c15f8fd7c4e5add29d7f64b87abdaa09"
|
|
||||||
|
|
||||||
absoluteVulnBlobPath, _ := filepath.Abs(filepath.Join(projectRootDir, vulnBlobPath))
|
layer, err := os.ReadFile(absoluteBlobPath) //nolint: lll
|
||||||
|
|
||||||
vulnerableLayer, err := os.ReadFile(absoluteVulnBlobPath) //nolint: lll
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return vulnerableLayer, nil
|
return layer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDefaultLayers() []Layer {
|
func GetDefaultLayers() []Layer {
|
||||||
|
|
Loading…
Reference in a new issue