0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00
zot/pkg/test/common_test.go

1274 lines
32 KiB
Go
Raw Normal View History

//go:build sync && scrub && metrics && search
// +build sync,scrub,metrics,search
package test_test
import (
"context"
"encoding/json"
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
"fmt"
"os"
"path"
"testing"
"time"
notconfig "github.com/notaryproject/notation-go/config"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
"golang.org/x/crypto/bcrypt"
"zotregistry.io/zot/pkg/api"
"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/test"
)
func TestCopyFiles(t *testing.T) {
Convey("sourceDir does not exist", t, func() {
err := test.CopyFiles("/path/to/some/unexisting/directory", os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("destDir is a file", t, func() {
dir := t.TempDir()
test.CopyTestFiles("../../test/data", dir)
err := test.CopyFiles(dir, "/etc/passwd")
So(err, ShouldNotBeNil)
})
Convey("sourceDir does not have read permissions", t, func() {
dir := t.TempDir()
err := os.Chmod(dir, 0o300)
So(err, ShouldBeNil)
err = test.CopyFiles(dir, os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("sourceDir has a subfolder that does not have read permissions", t, func() {
dir := t.TempDir()
sdir := "subdir"
err := os.Mkdir(path.Join(dir, sdir), 0o300)
So(err, ShouldBeNil)
err = test.CopyFiles(dir, os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("sourceDir has a file that does not have read permissions", t, func() {
dir := t.TempDir()
filePath := path.Join(dir, "file.txt")
err := os.WriteFile(filePath, []byte("some dummy file content"), 0o644) //nolint: gosec
if err != nil {
panic(err)
}
err = os.Chmod(filePath, 0o300)
So(err, ShouldBeNil)
err = test.CopyFiles(dir, os.TempDir())
So(err, ShouldNotBeNil)
})
Convey("sourceDir contains a folder starting with invalid characters", t, func() {
srcDir := t.TempDir()
dstDir := t.TempDir()
err := os.MkdirAll(path.Join(srcDir, "_trivy", "db"), 0o755)
if err != nil {
panic(err)
}
err = os.MkdirAll(path.Join(srcDir, "test-index"), 0o755)
if err != nil {
panic(err)
}
filePathTrivy := path.Join(srcDir, "_trivy", "db", "trivy.db")
err = os.WriteFile(filePathTrivy, []byte("some dummy file content"), 0o644) //nolint: gosec
if err != nil {
panic(err)
}
var index ispec.Index
content, err := json.Marshal(index)
if err != nil {
panic(err)
}
err = os.WriteFile(path.Join(srcDir, "test-index", "index.json"), content, 0o644) //nolint: gosec
if err != nil {
panic(err)
}
err = test.CopyFiles(srcDir, dstDir)
So(err, ShouldBeNil)
_, err = os.Stat(path.Join(dstDir, "_trivy", "db", "trivy.db"))
So(err, ShouldNotBeNil)
So(os.IsNotExist(err), ShouldBeTrue)
_, err = os.Stat(path.Join(dstDir, "test-index", "index.json"))
So(err, ShouldBeNil)
})
Convey("panic when sourceDir does not exist", t, func() {
So(func() { test.CopyTestFiles("/path/to/some/unexisting/directory", os.TempDir()) }, ShouldPanic)
})
}
func TestGetOciLayoutDigests(t *testing.T) {
dir := t.TempDir()
Convey("image path is wrong", t, func() {
So(func() { _, _, _ = test.GetOciLayoutDigests("inexistent-image") }, ShouldPanic)
})
Convey("no permissions when getting index", t, func() {
test.CopyTestFiles("../../test/data/zot-test", path.Join(dir, "test-index"))
err := os.Chmod(path.Join(dir, "test-index", "index.json"), 0o000)
if err != nil {
panic(err)
}
So(func() { _, _, _ = test.GetOciLayoutDigests(path.Join(dir, "test-index")) }, ShouldPanic)
err = os.Chmod(path.Join(dir, "test-index", "index.json"), 0o755)
if err != nil {
panic(err)
}
})
Convey("can't access manifest digest", t, func() {
test.CopyTestFiles("../../test/data/zot-test", path.Join(dir, "test-manifest"))
buf, err := os.ReadFile(path.Join(dir, "test-manifest", "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
err = os.Chmod(path.Join(dir, "test-manifest", "blobs/sha256", index.Manifests[0].Digest.Encoded()), 0o000)
if err != nil {
panic(err)
}
So(func() { _, _, _ = test.GetOciLayoutDigests(path.Join(dir, "test-manifest")) }, ShouldPanic)
err = os.Chmod(path.Join(dir, "test-manifest", "blobs/sha256", index.Manifests[0].Digest.Encoded()), 0o755)
if err != nil {
panic(err)
}
})
}
func TestGetImageComponents(t *testing.T) {
Convey("Inject failures for unreachable lines", t, func() {
injected := test.InjectFailure(0)
if injected {
_, _, _, err := test.GetImageComponents(100)
So(err, ShouldNotBeNil)
}
})
Convey("finishes successfully", t, func() {
_, _, _, err := test.GetImageComponents(100)
So(err, ShouldBeNil)
})
}
func TestWaitTillTrivyDBDownloadStarted(t *testing.T) {
Convey("finishes successfully", t, func() {
tempDir := t.TempDir()
go func() {
test.WaitTillTrivyDBDownloadStarted(tempDir)
}()
time.Sleep(test.SleepTime)
_, err := os.Create(path.Join(tempDir, "trivy.db"))
So(err, ShouldBeNil)
})
}
func TestControllerManager(t *testing.T) {
Convey("Test StartServer Init() panic", t, func() {
port := test.GetFreePort()
conf := config.New()
conf.HTTP.Port = port
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
// No storage configured
So(func() { ctlrManager.StartServer() }, ShouldPanic)
})
Convey("Test RunServer panic", t, func() {
tempDir := t.TempDir()
// Invalid port
conf := config.New()
conf.HTTP.Port = "999999"
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctx := context.Background()
err := ctlr.Init(ctx)
So(err, ShouldBeNil)
So(func() { ctlrManager.RunServer(ctx) }, ShouldPanic)
})
}
func TestUploadArtifact(t *testing.T) {
Convey("Put request results in an error", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
artifact := ispec.Artifact{}
err := test.UploadArtifact(baseURL, "test", &artifact)
So(err, ShouldNotBeNil)
})
}
func TestUploadBlob(t *testing.T) {
Convey("Post request results in an error", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
err := test.UploadBlob(baseURL, "test", []byte("test"), "zot.com.test")
So(err, ShouldNotBeNil)
})
Convey("Post request status differs from accepted", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
err := os.Chmod(tempDir, 0o400)
if err != nil {
t.Fatal(err)
}
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
err = test.UploadBlob(baseURL, "test", []byte("test"), "zot.com.test")
So(err, ShouldEqual, test.ErrPostBlob)
})
Convey("Put request results in an error", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
blob := new([]byte)
err := test.UploadBlob(baseURL, "test", *blob, "zot.com.test")
So(err, ShouldNotBeNil)
})
Convey("Put request status differs from accepted", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
blob := []byte("test")
blobDigest := godigest.FromBytes(blob)
layerPath := path.Join(tempDir, "test", "blobs", "sha256")
blobPath := path.Join(layerPath, blobDigest.String())
if _, err := os.Stat(layerPath); os.IsNotExist(err) {
err = os.MkdirAll(layerPath, 0o700)
if err != nil {
t.Fatal(err)
}
file, err := os.Create(blobPath)
if err != nil {
t.Fatal(err)
}
err = os.Chmod(layerPath, 0o000)
if err != nil {
t.Fatal(err)
}
defer func() {
err = os.Chmod(layerPath, 0o700)
if err != nil {
t.Fatal(err)
}
os.RemoveAll(file.Name())
}()
}
err := test.UploadBlob(baseURL, "test", blob, "zot.com.test")
So(err, ShouldEqual, test.ErrPutBlob)
})
Convey("Put request successful", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
blob := []byte("test")
err := test.UploadBlob(baseURL, "test", blob, "zot.com.test")
So(err, ShouldEqual, nil)
})
}
func TestUploadImage(t *testing.T) {
Convey("Post request results in an error", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = t.TempDir()
img := test.Image{
Layers: make([][]byte, 10),
}
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
})
Convey("Post request status differs from accepted", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
err := os.Chmod(tempDir, 0o400)
if err != nil {
t.Fatal(err)
}
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
img := test.Image{
Layers: make([][]byte, 10),
}
err = test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
})
Convey("Put request results in an error", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = t.TempDir()
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
img := test.Image{
Layers: make([][]byte, 10), // invalid format that will result in an error
Config: ispec.Image{},
}
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
})
Convey("Image uploaded successfully", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = t.TempDir()
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
layerBlob := []byte("test")
img := test.Image{
Layers: [][]byte{
layerBlob,
}, // invalid format that will result in an error
Config: ispec.Image{},
}
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
})
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
Convey("Upload image with authentification", t, func() {
tempDir := t.TempDir()
conf := config.New()
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
user1 := "test"
password1 := "test"
testString1 := getCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{
Path: htpasswdPath,
},
}
conf.HTTP.Port = port
conf.AccessControl = &config.AccessControlConfig{
Repositories: config.Repositories{
"repo": config.PolicyGroup{
Policies: []config.Policy{
{
Users: []string{user1},
Actions: []string{"read", "create"},
},
},
DefaultPolicy: []string{},
},
"inaccessibleRepo": config.PolicyGroup{
Policies: []config.Policy{
{
Users: []string{user1},
Actions: []string{"create"},
},
},
DefaultPolicy: []string{},
},
},
AdminPolicy: config.Policy{
Users: []string{},
Actions: []string{},
},
}
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = tempDir
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
Convey("Request fail while pushing layer", func() {
err := test.UploadImageWithBasicAuth(test.Image{Layers: [][]byte{{1, 2, 3}}}, "badURL", "", "", "")
So(err, ShouldNotBeNil)
})
Convey("Request status is not StatusOk while pushing layer", func() {
err := test.UploadImageWithBasicAuth(test.Image{Layers: [][]byte{{1, 2, 3}}}, baseURL, "repo", "", "")
So(err, ShouldNotBeNil)
})
Convey("Request fail while pushing config", func() {
err := test.UploadImageWithBasicAuth(test.Image{}, "badURL", "", "", "")
So(err, ShouldNotBeNil)
})
Convey("Request status is not StatusOk while pushing config", func() {
err := test.UploadImageWithBasicAuth(test.Image{}, baseURL, "repo", "", "")
So(err, ShouldNotBeNil)
})
})
Convey("Blob upload wrong response status code", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
layerBlob := []byte("test")
layerBlobDigest := godigest.FromBytes(layerBlob)
layerPath := path.Join(tempDir, "test", "blobs", "sha256")
if _, err := os.Stat(layerPath); os.IsNotExist(err) {
err = os.MkdirAll(layerPath, 0o700)
if err != nil {
t.Fatal(err)
}
file, err := os.Create(path.Join(layerPath, layerBlobDigest.Encoded()))
if err != nil {
t.Fatal(err)
}
err = os.Chmod(layerPath, 0o000)
if err != nil {
t.Fatal(err)
}
defer func() {
err = os.Chmod(layerPath, 0o700)
if err != nil {
t.Fatal(err)
}
os.RemoveAll(file.Name())
}()
}
img := test.Image{
Layers: [][]byte{
layerBlob,
}, // invalid format that will result in an error
Config: ispec.Image{},
}
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
})
Convey("CreateBlobUpload wrong response status code", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
layerBlob := []byte("test")
img := test.Image{
Layers: [][]byte{
layerBlob,
}, // invalid format that will result in an error
Config: ispec.Image{},
}
Convey("CreateBlobUpload", func() {
injected := test.InjectFailure(2)
if injected {
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
}
})
Convey("UpdateBlobUpload", func() {
injected := test.InjectFailure(4)
if injected {
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
}
})
})
}
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
func getCredString(username, password string) string {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil {
panic(err)
}
usernameAndHash := fmt.Sprintf("%s:%s", username, string(hash))
return usernameAndHash
}
func TestInjectUploadImage(t *testing.T) {
Convey("Inject failures for unreachable lines", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
layerBlob := []byte("test")
layerPath := path.Join(tempDir, "test", ".uploads")
if _, err := os.Stat(layerPath); os.IsNotExist(err) {
err = os.MkdirAll(layerPath, 0o700)
if err != nil {
t.Fatal(err)
}
}
img := test.Image{
Layers: [][]byte{
layerBlob,
}, // invalid format that will result in an error
Config: ispec.Image{},
}
Convey("first marshal", func() {
injected := test.InjectFailure(0)
if injected {
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
}
})
Convey("CreateBlobUpload POST call", func() {
injected := test.InjectFailure(1)
if injected {
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
}
})
Convey("UpdateBlobUpload PUT call", func() {
injected := test.InjectFailure(3)
if injected {
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
}
})
Convey("second marshal", func() {
injected := test.InjectFailure(5)
if injected {
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
}
})
})
}
func TestReadLogFileAndSearchString(t *testing.T) {
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
if err != nil {
panic(err)
}
logPath := logFile.Name()
defer os.Remove(logPath)
Convey("Invalid path", t, func() {
_, err = test.ReadLogFileAndSearchString("invalidPath", "DB update completed, next update scheduled", 90*time.Second)
So(err, ShouldNotBeNil)
})
Convey("Time too short", t, func() {
ok, err := test.ReadLogFileAndSearchString(logPath, "invalid string", time.Microsecond)
So(err, ShouldBeNil)
So(ok, ShouldBeFalse)
})
}
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
func TestInjectUploadImageWithBasicAuth(t *testing.T) {
Convey("Inject failures for unreachable lines", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
tempDir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = tempDir
user := "user"
password := "password"
testString := getCredString(user, password)
htpasswdPath := test.MakeHtpasswdFileFromString(testString)
defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{
Path: htpasswdPath,
},
}
ctlr := api.NewController(conf)
ctlrManager := test.NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
feat(repodb): Implement RepoDB for image specific information using boltdb/dynamodb (#979) * feat(repodb): implement a DB for image specific information using boltdb (cherry picked from commit e3cb60b8566d84158409815325083ed149175063) Some other fixes/improvements on top (Andrei) Global search: The last updated attribute on repo level is now computed correctly. Global search: Fix and enhance tests: validate more fields, and fix CVE verification logic RepoListWithNewestImage: The vendors and platforms at repo level are no longer containing duplicate entries CVE: scan OCIUncompressedLayer instead of skiping them (used in tests) bug(repodb): do no try to increment download counters for signatures Signed-off-by: Andrei Aaron <andaaron@cisco.com> Add filtering to global search API (Laurentiu) (cherry picked from commit a87976d635ea876fe8ced532e8adb7c3bb24098f) Original work by Laurentiu Niculae <niculae.laurentiu1@gmail.com> Fix pagination bug - when limit was bigger than the repo count result contained empty results - now correctly returns only maximum available number of repo results Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Add history to the fields returned from RepoDB Consolidate fields used in packages - pkg/extensions/search/common/common_test - pkg/extensions/search/common/common Refactor duplicate code in GlobalSearch verification Add vulnerability scan results to image:tag reply Signed-off-by: Andrei Aaron <andaaron@cisco.com> Refactor ExpandedRepoInfo to using RepoDB Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit fd7dc85c3a9d028fd8860d3791cad4df769ed005) Init RepoDB at startup - sync with storage - ignore images without a tag Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 359898facd6541b2aa99ee95080f7aabf28c2650) Update request to get image:tag to use repodb Signed-off-by: Andrei Aaron <andaaron@cisco.com> Sync RepoDB logging - added logging for errors Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 2e128f4d01712b34c70b5468285100b0657001bb) sync-repodb minor error checking fix Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Improve tests for syncing RepoDB with storage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit b18408c6d64e01312849fc18b929e3a2a7931e9e) Update scoring rule for repos - now prioritize matches to the end of the repo name Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 6961346ccf02223132b3b12a2132c80bd1b6b33c) Upgrade search filters to permit multiple values - multiple values for os and arch Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 3ffb72c6fc0587ff827a03fe4f76a13b27b876a0) feature(repodb): add pagination for RepoListWithNewestImage Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> (cherry picked from commit 32c917f2dc65363b0856345289353559a8027aee) test(fix): fix tests failing since repodb is used for listing all repos 1. One of the tests was verifying disk/oci related erros and is not applicable 2. Another test was actually broken in an older PR, the default store and the substore were using the same repo names (the substore ones were unprefixed), which should not be the case, this was causing a single entry to show in the RepoDB instead of two separate entries for each test image Root cause in: https://github.com/project-zot/zot/commit/b61aff62cd5088314cee39fae42cec0ad855bd7c#diff-b86e11fa5a3102b336caebec3b30a9d35e26af554dd8658f124dba2404b7d24aR88 Signed-off-by: Andrei Aaron <andaaron@cisco.com> chore: move code reponsible for transforming objects to gql_generated types to separate package Signed-off-by: Andrei Aaron <andaaron@cisco.com> Process input for global search - Clean input: query, filter strings - Add validation for global search input Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit f1ca8670fbe4a4a327ea25cf459237dbf23bb78a) fix: only call cve scanning for data shown to the user Signed-off-by: Andrei Aaron <andaaron@cisco.com> GQL omit scanning for CVE if field is not required Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit 5479ce45d6cb2abcf5fbccadeaf6f3393c3f6bf1) Fix filtering logic in RepoDB - filter parameter was set to false instead of being calculator from the later image Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit a82d2327e34e5da617af0b7ca78a2dba90999f0a) bug(repodb): Checking signature returns error if signed image is not found - we considere a signature image orfan when the image it signs is not found - we need this to ignore such signatures in certain cases Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> (cherry picked from commit d0418505f76467accd8e1ee34fcc2b2a165efae5) feat(repodb): CVE logic to use repoDB Also update some method signatures to remove usage of: github.com/google/go-containerregistry/pkg/v1 Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): refactor repodb update logic Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): minor fixes Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): move repodb logic inside meta directory under pkg Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): change factory class for repodb initialization with factory metrod Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): simplify repodb configuration - repodb now shares config parameters with the cache - config taken directly from storage config Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(authors): fix authors information to work properly with repodb Ideally this commit would be squshed in the repodb commit but as-is it is easier to cherry-pick on other branches Signed-off-by: Andrei Aaron <andaaron@cisco.com> * feat(repodb): dynamodb support for repodb - clean-up repodb code + coverage improvements Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(dynamo): tables used by dynamo are created automatically if they don't exists - if the table exists nothing happens Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * test(repodb): coverage tests - minor fix for CVEListForImage to fix the tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): add descriptor with media type - to represent images and multi-arch images Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): support signatures on repo level - added to follow the behavior of signing and signature verification tools that work on a manifest level for each repo - all images with different tags but the same manifest will be signed at once Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): old repodb version migration support Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): tests for coverage Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): WIP fixing tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * feat(repodb): work on patchRepoDB tests Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(repodb): create dynamo tables only for linux amd Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> * fix(ci): fix a typo in ci-cd.yml Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Andrei Aaron <andaaron@cisco.com> Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Andrei Aaron <andaaron@cisco.com> Co-authored-by: Andrei Aaron <aaaron@luxoft.com>
2023-01-09 15:37:44 -05:00
layerBlob := []byte("test")
layerPath := path.Join(tempDir, "test", ".uploads")
if _, err := os.Stat(layerPath); os.IsNotExist(err) {
err = os.MkdirAll(layerPath, 0o700)
if err != nil {
t.Fatal(err)
}
}
img := test.Image{
Layers: [][]byte{
layerBlob,
}, // invalid format that will result in an error
Config: ispec.Image{},
}
Convey("first marshal", func() {
injected := test.InjectFailure(0)
if injected {
err := test.UploadImageWithBasicAuth(img, baseURL, "test", "user", "password")
So(err, ShouldNotBeNil)
}
})
Convey("CreateBlobUpload POST call", func() {
injected := test.InjectFailure(1)
if injected {
err := test.UploadImageWithBasicAuth(img, baseURL, "test", "user", "password")
So(err, ShouldNotBeNil)
}
})
Convey("UpdateBlobUpload PUT call", func() {
injected := test.InjectFailure(3)
if injected {
err := test.UploadImageWithBasicAuth(img, baseURL, "test", "user", "password")
So(err, ShouldNotBeNil)
}
})
Convey("second marshal", func() {
injected := test.InjectFailure(5)
if injected {
err := test.UploadImageWithBasicAuth(img, baseURL, "test", "user", "password")
So(err, ShouldNotBeNil)
}
})
})
}
func TestCopyFile(t *testing.T) {
Convey("destFilePath does not exist", t, func() {
err := test.CopyFile("/path/to/srcFile", "~/path/to/some/unexisting/destDir/file")
So(err, ShouldNotBeNil)
})
Convey("sourceFile does not exist", t, func() {
err := test.CopyFile("/path/to/some/unexisting/file", path.Join(t.TempDir(), "destFile.txt"))
So(err, ShouldNotBeNil)
})
}
func TestIsDigestReference(t *testing.T) {
Convey("not digest reference", t, func() {
res := test.IsDigestReference("notDigestReference/input")
So(res, ShouldBeFalse)
})
Convey("wrong input format", t, func() {
res := test.IsDigestReference("wrongInput")
So(res, ShouldBeFalse)
})
}
func TestLoadNotationSigningkeys(t *testing.T) {
Convey("notation directory doesn't exist", t, func() {
_, err := test.LoadNotationSigningkeys(t.TempDir())
So(err, ShouldNotBeNil)
})
Convey("wrong content of signingkeys.json", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
err := os.Mkdir(dir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(dir, "signingkeys.json")
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
_, err = test.LoadNotationSigningkeys(tempDir)
So(err, ShouldNotBeNil)
})
Convey("not enough permissions to access signingkeys.json", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
err := os.Mkdir(dir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(dir, "signingkeys.json")
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o300) //nolint: gosec
So(err, ShouldBeNil)
_, err = test.LoadNotationSigningkeys(tempDir)
So(err, ShouldNotBeNil)
})
Convey("signingkeys.json not exists so it is created successfully", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
err := os.Mkdir(dir, 0o777)
So(err, ShouldBeNil)
_, err = test.LoadNotationSigningkeys(tempDir)
So(err, ShouldBeNil)
})
Convey("signingkeys.json not exists - error trying to create it", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
// create notation directory without write permissions
err := os.Mkdir(dir, 0o555)
So(err, ShouldBeNil)
_, err = test.LoadNotationSigningkeys(tempDir)
So(err, ShouldNotBeNil)
})
}
func TestLoadNotationConfig(t *testing.T) {
Convey("directory doesn't exist", t, func() {
_, err := test.LoadNotationConfig(t.TempDir())
So(err, ShouldNotBeNil)
})
Convey("wrong content of signingkeys.json", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
err := os.Mkdir(dir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(dir, "signingkeys.json")
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
_, err = test.LoadNotationConfig(tempDir)
So(err, ShouldNotBeNil)
})
Convey("check default value of signature format", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
err := os.Mkdir(dir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(dir, "signingkeys.json")
err = os.WriteFile(filePath, []byte("{\"SignatureFormat\": \"\"}"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
configInfo, err := test.LoadNotationConfig(tempDir)
So(err, ShouldBeNil)
So(configInfo.SignatureFormat, ShouldEqual, "jws")
})
}
func TestSignWithNotation(t *testing.T) {
Convey("notation directory doesn't exist", t, func() {
err := test.SignWithNotation("key", "reference", t.TempDir())
So(err, ShouldNotBeNil)
})
Convey("key not found", t, func() {
tempDir := t.TempDir()
dir := path.Join(tempDir, "notation")
err := os.Mkdir(dir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(dir, "signingkeys.json")
err = os.WriteFile(filePath, []byte("{}"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
err = test.SignWithNotation("key", "reference", tempDir)
So(err, ShouldEqual, test.ErrKeyNotFound)
})
Convey("not enough permissions to access notation/localkeys dir", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, "key")
So(err, ShouldBeNil)
err = os.Chmod(path.Join(tdir, "notation", "localkeys"), 0o000)
So(err, ShouldBeNil)
err = test.SignWithNotation("key", "reference", tdir)
So(err, ShouldNotBeNil)
err = os.Chmod(path.Join(tdir, "notation", "localkeys"), 0o755)
So(err, ShouldBeNil)
})
Convey("error parsing reference", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, "key")
So(err, ShouldBeNil)
err = test.SignWithNotation("key", "invalidReference", tdir)
So(err, ShouldNotBeNil)
})
Convey("error signing", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, "key")
So(err, ShouldBeNil)
err = test.SignWithNotation("key", "localhost:8080/invalidreference:1.0", tdir)
So(err, ShouldNotBeNil)
})
}
func TestVerifyWithNotation(t *testing.T) {
Convey("notation directory doesn't exist", t, func() {
err := test.VerifyWithNotation("reference", t.TempDir())
So(err, ShouldNotBeNil)
})
Convey("error parsing reference", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, "key")
So(err, ShouldBeNil)
err = test.VerifyWithNotation("invalidReference", tdir)
So(err, ShouldNotBeNil)
})
Convey("error trying to get manifest", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tdir)
err = test.GenerateNotationCerts(tdir, "key")
So(err, ShouldBeNil)
err = test.VerifyWithNotation("localhost:8080/invalidreference:1.0", tdir)
So(err, ShouldNotBeNil)
})
Convey("invalid content of trustpolicy.json", t, func() {
// start a new server
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
dir := t.TempDir()
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = dir
ctlr := api.NewController(conf)
cm := test.NewControllerManager(ctlr)
// this blocks
cm.StartAndWait(port)
defer cm.StopServer()
repoName := "signed-repo"
tag := "1.0"
cfg, layers, manifest, err := test.GetImageComponents(2)
So(err, ShouldBeNil)
err = test.UploadImage(
test.Image{
Config: cfg,
Layers: layers,
Manifest: manifest,
Tag: tag,
}, baseURL, repoName)
So(err, ShouldBeNil)
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
tempDir := t.TempDir()
notationDir := path.Join(tempDir, "notation")
err = os.Mkdir(notationDir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(notationDir, "trustpolicy.json")
err = os.WriteFile(filePath, []byte("some dummy file content"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tempDir)
err = test.VerifyWithNotation(fmt.Sprintf("localhost:%s/%s:%s", port, repoName, tag), tempDir)
So(err, ShouldNotBeNil)
})
}
func TestListNotarySignatures(t *testing.T) {
Convey("error parsing reference", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
_, err = test.ListNotarySignatures("invalidReference", tdir)
So(err, ShouldNotBeNil)
})
Convey("error trying to get manifest", t, func() {
cwd, err := os.Getwd()
So(err, ShouldBeNil)
defer func() { _ = os.Chdir(cwd) }()
tdir := t.TempDir()
_ = os.Chdir(tdir)
_, err = test.ListNotarySignatures("localhost:8080/invalidreference:1.0", tdir)
So(err, ShouldNotBeNil)
})
}
func TestGenerateNotationCerts(t *testing.T) {
Convey("write key file with permission", t, func() {
tempDir := t.TempDir()
notationDir := path.Join(tempDir, "notation")
err := os.Mkdir(notationDir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(notationDir, "localkeys")
err = os.WriteFile(filePath, []byte("{}"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tempDir)
err = test.GenerateNotationCerts(t.TempDir(), "cert")
So(err, ShouldNotBeNil)
})
Convey("write cert file with permission", t, func() {
tempDir := t.TempDir()
notationDir := path.Join(tempDir, "notation", "localkeys")
err := os.MkdirAll(notationDir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(notationDir, "cert.crt")
err = os.WriteFile(filePath, []byte("{}"), 0o666) //nolint: gosec
So(err, ShouldBeNil)
err = os.Chmod(filePath, 0o000)
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tempDir)
err = test.GenerateNotationCerts(t.TempDir(), "cert")
So(err, ShouldNotBeNil)
err = os.Chmod(filePath, 0o755)
So(err, ShouldBeNil)
})
Convey("signingkeys.json file - not enough permission", t, func() {
tempDir := t.TempDir()
notationDir := path.Join(tempDir, "notation")
err := os.Mkdir(notationDir, 0o777)
So(err, ShouldBeNil)
filePath := path.Join(notationDir, "signingkeys.json")
_, err = os.Create(filePath) //nolint: gosec
So(err, ShouldBeNil)
err = os.Chmod(filePath, 0o000)
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tempDir)
err = test.GenerateNotationCerts(t.TempDir(), "cert")
So(err, ShouldNotBeNil)
err = os.Remove(filePath)
So(err, ShouldBeNil)
err = os.RemoveAll(path.Join(notationDir, "localkeys"))
So(err, ShouldBeNil)
signingKeysBuf, err := json.Marshal(notconfig.SigningKeys{})
So(err, ShouldBeNil)
err = os.WriteFile(filePath, signingKeysBuf, 0o555)
So(err, ShouldBeNil)
err = test.GenerateNotationCerts(t.TempDir(), "cert")
So(err, ShouldNotBeNil)
})
Convey("keysuite already exists in signingkeys.json", t, func() {
tempDir := t.TempDir()
notationDir := path.Join(tempDir, "notation")
err := os.Mkdir(notationDir, 0o777)
So(err, ShouldBeNil)
certName := "cert-test"
filePath := path.Join(notationDir, "signingkeys.json")
keyPath := path.Join(notationDir, "localkeys", certName+".key")
certPath := path.Join(notationDir, "localkeys", certName+".crt")
signingKeys := notconfig.SigningKeys{}
keySuite := notconfig.KeySuite{
Name: certName,
X509KeyPair: &notconfig.X509KeyPair{
KeyPath: keyPath,
CertificatePath: certPath,
},
}
signingKeys.Keys = []notconfig.KeySuite{keySuite}
signingKeysBuf, err := json.Marshal(signingKeys)
So(err, ShouldBeNil)
err = os.WriteFile(filePath, signingKeysBuf, 0o600)
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tempDir)
err = test.GenerateNotationCerts(t.TempDir(), certName)
So(err, ShouldNotBeNil)
})
Convey("truststore files", t, func() {
tempDir := t.TempDir()
notationDir := path.Join(tempDir, "notation")
err := os.Mkdir(notationDir, 0o777)
So(err, ShouldBeNil)
certName := "cert-test"
trustStorePath := path.Join(notationDir, fmt.Sprintf("truststore/x509/ca/%s", certName))
err = os.MkdirAll(trustStorePath, 0o755)
So(err, ShouldBeNil)
err = os.Chmod(path.Join(notationDir, "truststore/x509"), 0o000)
So(err, ShouldBeNil)
test.NotationPathLock.Lock()
defer test.NotationPathLock.Unlock()
test.LoadNotationPath(tempDir)
err = test.GenerateNotationCerts(tempDir, certName)
So(err, ShouldNotBeNil)
err = os.RemoveAll(path.Join(notationDir, "localkeys"))
So(err, ShouldBeNil)
err = os.Chmod(path.Join(notationDir, "truststore/x509"), 0o755)
So(err, ShouldBeNil)
_, err = os.Create(path.Join(trustStorePath, "cert-test.crt"))
So(err, ShouldBeNil)
err = test.GenerateNotationCerts(tempDir, certName)
So(err, ShouldNotBeNil)
err = os.RemoveAll(path.Join(notationDir, "localkeys"))
So(err, ShouldBeNil)
err = os.Remove(path.Join(trustStorePath, "cert-test.crt"))
So(err, ShouldBeNil)
err = os.Chmod(path.Join(notationDir, "truststore/x509/ca", certName), 0o555)
So(err, ShouldBeNil)
err = test.GenerateNotationCerts(tempDir, certName)
So(err, ShouldNotBeNil)
})
}