From 5f230bd8ff0ab6bf42307b80080df8a5ea43f954 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 19 Aug 2020 00:10:49 -0700 Subject: [PATCH] Added unit test cases --- BUILD.bazel | 2 +- Makefile | 2 +- codecov.yml | 4 + pkg/extensions/search/cve/BUILD.bazel | 6 +- pkg/extensions/search/cve/cve_test.go | 488 +++++++++++++++++++++++++- 5 files changed, 498 insertions(+), 4 deletions(-) create mode 100644 codecov.yml diff --git a/BUILD.bazel b/BUILD.bazel index aac52570..cbc45f77 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -94,7 +94,7 @@ go_library( filegroup( name = "exported_testdata", srcs = glob([ - "test/data/*", + "test/data/**", ]), visibility = ["//visibility:public"], ) diff --git a/Makefile b/Makefile index 47e7a711..93e2e2b5 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ debug: doc .PHONY: test test: - $(shell mkdir -p test/data; cd test/data; ../scripts/gen_certs.sh; cd ${TOP_LEVEL}) + $(shell mkdir -p test/data; cd test/data; ../scripts/gen_certs.sh; cd ${TOP_LEVEL}; sudo skopeo --insecure-policy copy -q docker://centos:latest oci:${TOP_LEVEL}/test/data/zot-test:0.0.1) go test -v -race -cover -coverpkg ./... -coverprofile=coverage.txt -covermode=atomic ./... .PHONY: covhtml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..09aaabed --- /dev/null +++ b/codecov.yml @@ -0,0 +1,4 @@ +ignore: + - "*_gen.go" + - "./pkg/extensions/search/*_gen.go" + - "./pkg/extensions/search/generated.go" \ No newline at end of file diff --git a/pkg/extensions/search/cve/BUILD.bazel b/pkg/extensions/search/cve/BUILD.bazel index 22b108c3..4568b77f 100644 --- a/pkg/extensions/search/cve/BUILD.bazel +++ b/pkg/extensions/search/cve/BUILD.bazel @@ -24,10 +24,14 @@ go_library( go_test( name = "go_default_test", srcs = ["cve_test.go"], - data = glob(["testdata/**"]), + data = [ + "//:exported_testdata", + ], embed = [":go_default_library"], deps = [ + "//pkg/api:go_default_library", "//pkg/log:go_default_library", "@com_github_smartystreets_goconvey//convey:go_default_library", + "@in_gopkg_resty_v1//:go_default_library", ], ) diff --git a/pkg/extensions/search/cve/cve_test.go b/pkg/extensions/search/cve/cve_test.go index d467779d..00838420 100644 --- a/pkg/extensions/search/cve/cve_test.go +++ b/pkg/extensions/search/cve/cve_test.go @@ -1,13 +1,22 @@ +// nolint: lll package cveinfo_test import ( + "context" + "encoding/json" + "fmt" + "io" "io/ioutil" "os" + "path" "testing" + "time" + "github.com/anuvu/zot/pkg/api" cveinfo "github.com/anuvu/zot/pkg/extensions/search/cve" "github.com/anuvu/zot/pkg/log" . "github.com/smartystreets/goconvey/convey" + "gopkg.in/resty.v1" ) // nolint:gochecknoglobals @@ -16,6 +25,32 @@ var ( dbDir string ) +const ( + BaseURL1 = "http://127.0.0.1:8085" + SecurePort1 = "8085" + username = "test" + passphrase = "test" +) + +type CveResult struct { + ImgList ImgList `json:"data"` +} + +type ImgList struct { + CVEResultForImage CVEResultForImage `json:"CVEListForImage"` +} + +type CVEResultForImage struct { + Tag string `json:"Tag"` + CVEList []CVE `json:"CVEList"` +} + +type CVE struct { + ID string `json:"Id"` + Description string `json:"Description"` + Severity string `json:"Severity"` +} + func testSetup() error { dir, err := ioutil.TempDir("", "util_test") if err != nil { @@ -26,15 +61,466 @@ func testSetup() error { dbDir = dir + err = copyFiles("../../../../test/data/zot-test", path.Join(dbDir, "zot-test")) + if err != nil { + return err + } + + err = generateTestData() + if err != nil { + return err + } + return nil } +func generateTestData() error { + // Image dir with no files + err := os.Mkdir(path.Join(dbDir, "zot-noindex-test"), 0755) + if err != nil { + return err + } + + // Image dir with invalid index.json + err = os.Mkdir(path.Join(dbDir, "zot-squashfs-invalid-index"), 0755) + if err != nil { + return err + } + + content := fmt.Sprintf(`{"schemaVersion": 2,"manifests"[{"mediaType": "application/vnd.oci.image.manifest.v1+json","digest": "sha256:2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929","size": 1240,"annotations": {"org.opencontainers.image.ref.name": "commit-aaa7c6e7-squashfs"},"platform": {"architecture": "amd64","os": "linux"}}]}`) + + err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-index", "index.json"), content) + if err != nil { + return err + } + + // Image dir with no blobs + err = os.Mkdir(path.Join(dbDir, "zot-squashfs-noblobs"), 0755) + if err != nil { + return err + } + + content = fmt.Sprintf(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929","size":1240,"annotations":{"org.opencontainers.image.ref.name":"commit-aaa7c6e7-squashfs"},"platform":{"architecture":"amd64","os":"linux"}}]} + `) + + err = makeTestFile(path.Join(dbDir, "zot-squashfs-noblobs", "index.json"), content) + if err != nil { + return err + } + + // Image dir with invalid blob + err = os.MkdirAll(path.Join(dbDir, "zot-squashfs-invalid-blob", "blobs/sha256"), 0755) + if err != nil { + return err + } + + content = fmt.Sprintf(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929","size":1240,"annotations":{"org.opencontainers.image.ref.name":"commit-aaa7c6e7-squashfs"},"platform":{"architecture":"amd64","os":"linux"}}]} + `) + + err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-blob", "index.json"), content) + if err != nil { + return err + } + + content = fmt.Sprintf(`{"schemaVersion":2,"config"{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:4b37d4133908ac9a3032ba996020f2ad41354a616b071ca7e726a1df18a0f354","size":1691},"layers":[{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:a01a66356aace53222e92fb6fd990b23eb44ab0e58dff6f853fa9f771ecf3ac5","size":54996992},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:91c26d6934ef2b5c5c4d8458af9bfc4ca46cf90c22380193154964abc8298a7a","size":52330496},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:f281a550ca49746cfc6b8f1ac52f8086b3d5845db2ca18fde980dab62ae3bf7d","size":23343104},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:7ee02568717acdda336c9d56d4dc6ea7f3b1c553e43bb0c0ecc6fd3bbd059d1a","size":5910528},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:8fb33b130588b239235dedd560cdf49d29bbf6f2db5419ac68e4592a85c1f416","size":123269120},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:1b49f0b33d4a696bb94d84c9acab3623e2c195bfb446d446a583a2f9f27b04c3","size":113901568}],"annotations":{"com.cisco.stacker.git_version":"7-dev19-63-gaaa7c6e7","ws.tycho.stacker.git_version":"0.3.26"}} + `) + + err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-blob", "blobs/sha256", "2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929"), content) + if err != nil { + return err + } + + // Image dir to test squashfs media type + err = os.MkdirAll(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256"), 0755) + if err != nil { + return err + } + + content = fmt.Sprintf(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929","size":1240,"annotations":{"org.opencontainers.image.ref.name":"commit-aaa7c6e7-squashfs"},"platform":{"architecture":"amd64","os":"linux"}}]} + `) + + err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-blob", "index.json"), content) + if err != nil { + return err + } + + content = fmt.Sprintf(`{"schemaVersion":2,"config"{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:4b37d4133908ac9a3032ba996020f2ad41354a616b071ca7e726a1df18a0f354","size":1691},"layers":[{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:a01a66356aace53222e92fb6fd990b23eb44ab0e58dff6f853fa9f771ecf3ac5","size":54996992},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:91c26d6934ef2b5c5c4d8458af9bfc4ca46cf90c22380193154964abc8298a7a","size":52330496},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:f281a550ca49746cfc6b8f1ac52f8086b3d5845db2ca18fde980dab62ae3bf7d","size":23343104},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:7ee02568717acdda336c9d56d4dc6ea7f3b1c553e43bb0c0ecc6fd3bbd059d1a","size":5910528},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:8fb33b130588b239235dedd560cdf49d29bbf6f2db5419ac68e4592a85c1f416","size":123269120},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:1b49f0b33d4a696bb94d84c9acab3623e2c195bfb446d446a583a2f9f27b04c3","size":113901568}],"annotations":{"com.cisco.stacker.git_version":"7-dev19-63-gaaa7c6e7","ws.tycho.stacker.git_version":"0.3.26"}} + `) + + err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-blob", "blobs/sha256", "2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929"), content) + if err != nil { + return err + } + + return nil +} + +func makeTestFile(fileName string, content string) error { + if err := ioutil.WriteFile(fileName, []byte(content), 0600); err != nil { + panic(err) + } + + return nil +} + +func copyFiles(sourceDir string, destDir string) error { + sourceMeta, err := os.Stat(sourceDir) + if err != nil { + return err + } + + if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil { + return err + } + + files, err := ioutil.ReadDir(sourceDir) + if err != nil { + return err + } + + for _, file := range files { + sourceFilePath := path.Join(sourceDir, file.Name()) + destFilePath := path.Join(destDir, file.Name()) + + if file.IsDir() { + if err = copyFiles(sourceFilePath, destFilePath); err != nil { + return err + } + } else { + sourceFile, err := os.Open(sourceFilePath) + if err != nil { + return err + } + defer sourceFile.Close() + + destFile, err := os.Create(destFilePath) + if err != nil { + return err + } + defer destFile.Close() + + if _, err = io.Copy(destFile, sourceFile); err != nil { + return err + } + } + } + + return nil +} + +func makeHtpasswdFile() string { + f, err := ioutil.TempFile("", "htpasswd-") + if err != nil { + panic(err) + } + + // bcrypt(username="test", passwd="test") + content := []byte("test:$2y$05$hlbSXDp6hzDLu6VwACS39ORvVRpr3OMR4RlJ31jtlaOEGnPjKZI1m\n") + if err := ioutil.WriteFile(f.Name(), content, 0600); err != nil { + panic(err) + } + + return f.Name() +} + func TestDownloadDB(t *testing.T) { Convey("Download DB", t, func() { err := testSetup() So(err, ShouldBeNil) err = cveinfo.UpdateCVEDb(dbDir, cve.Log) So(err, ShouldBeNil) - os.RemoveAll(dbDir) + + err = cveinfo.UpdateCVEDb("./testdata1", cve.Log) + So(err, ShouldNotBeNil) + }) +} + +func TestImageFormat(t *testing.T) { + Convey("Test valid image", t, func() { + isValidImage, err := cve.IsValidImageFormat(path.Join(dbDir, "zot-test")) + So(err, ShouldBeNil) + So(isValidImage, ShouldEqual, true) + + isValidImage, err = cve.IsValidImageFormat(path.Join(dbDir, "zot-noindex-test")) + So(err, ShouldNotBeNil) + So(isValidImage, ShouldEqual, false) + }) +} + +func TestImageTag(t *testing.T) { + Convey("Test image tag", t, func() { + imageTags, err := cve.GetImageTagsWithTimestamp(dbDir, "zot-test") + So(err, ShouldBeNil) + So(len(imageTags), ShouldNotEqual, 0) + + imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-tes") + So(err, ShouldNotBeNil) + So(imageTags, ShouldBeNil) + + imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-noindex-test") + So(err, ShouldNotBeNil) + So(len(imageTags), ShouldEqual, 0) + + imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-squashfs-noblobs") + So(err, ShouldNotBeNil) + So(len(imageTags), ShouldEqual, 0) + + imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-squashfs-invalid-index") + So(err, ShouldNotBeNil) + So(len(imageTags), ShouldEqual, 0) + + imageTags, err = cve.GetImageTagsWithTimestamp(dbDir, "zot-squashfs-invalid-blob") + So(err, ShouldNotBeNil) + So(len(imageTags), ShouldEqual, 0) + }) +} + +func TestCVESearch(t *testing.T) { + Convey("Test image vulenrability scanning", t, func() { + config := api.NewConfig() + config.HTTP.Port = SecurePort1 + htpasswdPath := makeHtpasswdFile() + defer os.Remove(htpasswdPath) + + config.HTTP.Auth = &api.AuthConfig{ + HTPasswd: api.AuthHTPasswd{ + Path: htpasswdPath, + }, + } + c := api.NewController(config) + defer os.RemoveAll(dbDir) + c.Config.Storage.RootDirectory = dbDir + cveConfig := &api.CVEConfig{ + UpdateInterval: 2, + } + searchConfig := &api.SearchConfig{ + CVE: cveConfig, + } + c.Config.Extensions = &api.ExtensionConfig{ + Search: searchConfig, + } + go func() { + // this blocks + if err := c.Run(); err != nil { + return + } + }() + + // wait till ready + for { + _, err := resty.R().Get(BaseURL1) + if err == nil { + break + } + time.Sleep(100 * time.Millisecond) + } + + defer func() { + ctx := context.Background() + _ = c.Server.Shutdown(ctx) + }() + + // without creds, should get access error + resp, err := resty.R().Get(BaseURL1 + "/v2/") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 401) + var e api.Error + err = json.Unmarshal(resp.Body(), &e) + So(err, ShouldBeNil) + + resp, err = resty.R().Get(BaseURL1 + "/query/") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 401) + err = json.Unmarshal(resp.Body(), &e) + So(err, ShouldBeNil) + + // with creds, should get expected status code + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 404) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/v2/") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + var cveResult CveResult + err = json.Unmarshal(resp.Body(), &cveResult) + So(err, ShouldBeNil) + So(len(cveResult.ImgList.CVEResultForImage.CVEList), ShouldNotBeZeroValue) + + id := cveResult.ImgList.CVEResultForImage.CVEList[0].ID + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListForCVE(id:\"" + id + "\"){Name%20Tags}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListWithCVEFixed(id:\"" + id + "\",image:\"zot-test\"){Tags{Name%20Timestamp}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-squashfs-test:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + var cveSquashFSResult CveResult + err = json.Unmarshal(resp.Body(), &cveSquashFSResult) + So(err, ShouldBeNil) + So(len(cveSquashFSResult.ImgList.CVEResultForImage.CVEList), ShouldBeZeroValue) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-squashfs-noindex:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListWithCVEFixed(id:\"" + id + "\",image:\"zot-squashfs-noindex\"){Tags{Name%20Timestamp}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-squashfs-invalid-index:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListWithCVEFixed(id:\"" + id + "\",image:\"zot-squashfs-invalid-index\"){Tags{Name%20Timestamp}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-squashfs-noblobs:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListWithCVEFixed(id:\"" + id + "\",image:\"zot-squashfs-noblob\"){Tags{Name%20Timestamp}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-squashfs-invalid-blob:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListWithCVEFixed(id:\"" + id + "\",image:\"zot-squashfs-invalid-blob\"){Tags{Name%20Timestamp}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-squashfs-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"cntos\"){Tag%20CVEList{Id%20Description%20Severity}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListForCVE(id:\"CVE-201-20482\"){Name%20Tags}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description%20Severity}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description%20Severity}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Severity}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + + // Testing Invalid Search URL + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){Ta%20CVEList{Id%20Description%20Severity}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 422) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListForCVE(tet:\"CVE-2018-20482\"){Name%20Tags}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 422) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageistForCVE(id:\"CVE-2018-20482\"){Name%20Tags}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 422) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={ImageListForCVE(id:\"CVE-2018-20482\"){ame%20Tags}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 422) + + resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(BaseURL1 + "/query?query={CVEListForImage(reo:\"zot-test:1.0.0\"){Tag%20CVEList{Id%20Description%20Severity}}}") + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 422) + }) +} + +func TestCveConfig(t *testing.T) { + updateDuration, _ := time.ParseDuration("1h") + expectedDuration, _ := time.ParseDuration("2h") + + Convey("Make a new cve config", t, func() { + config := api.NewConfig() + config.HTTP.Port = SecurePort1 + cveConfig := &api.CVEConfig{ + UpdateInterval: updateDuration, + } + searchConfig := &api.SearchConfig{ + CVE: cveConfig, + } + config.Extensions = &api.ExtensionConfig{ + Search: searchConfig, + } + c := api.NewController(config) + dir, err := ioutil.TempDir("", "oci-repo-test") + if err != nil { + panic(err) + } + defer os.RemoveAll(dir) + c.Config.Storage.RootDirectory = dir + + go func() { + // this blocks + if err := c.Run(); err != nil { + return + } + }() + + // wait till ready + for { + _, err := resty.R().Get(BaseURL1) + if err == nil { + break + } + time.Sleep(100 * time.Millisecond) + } + + So(c.Config.Extensions.Search.CVE.UpdateInterval, ShouldEqual, expectedDuration) + + defer func() { + ctx := context.Background() + _ = c.Server.Shutdown(ctx) + }() }) }