0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2025-01-06 22:40:28 -05:00
zot/pkg/extensions/lint/lint_test.go
peusebiu b80deb9927
refactor(storage): refactor storage into a single ImageStore (#1656)
unified both local and s3 ImageStore logic into a single ImageStore
added a new driver interface for common file/dirs manipulations
to be implemented by different storage types

refactor(gc): drop umoci dependency, implemented internal gc

added retentionDelay config option that specifies
the garbage collect delay for images without tags

this will also clean manifests which are part of an index image
(multiarch) that no longer exist.

fix(dedupe): skip blobs under .sync/ directory

if startup dedupe is running while also syncing is running
ignore blobs under sync's temporary storage

fix(storage): do not allow image indexes modifications

when deleting a manifest verify that it is not part of a multiarch image
and throw a MethodNotAllowed error to the client if it is.
we don't want to modify multiarch images

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
2023-09-01 10:54:39 -07:00

903 lines
28 KiB
Go

//go:build lint
// +build lint
package lint_test
import (
"encoding/json"
"fmt"
"net/http"
"os"
"path"
"testing"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"
"zotregistry.io/zot/pkg/api"
"zotregistry.io/zot/pkg/api/config"
extconf "zotregistry.io/zot/pkg/extensions/config"
"zotregistry.io/zot/pkg/extensions/lint"
"zotregistry.io/zot/pkg/extensions/monitoring"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/storage/local"
"zotregistry.io/zot/pkg/test"
)
const (
username = "test"
passphrase = "test"
ServerCert = "../../test/data/server.cert"
ServerKey = "../../test/data/server.key"
CACert = "../../test/data/ca.crt"
AuthorizedNamespace = "everyone/isallowed"
UnauthorizedNamespace = "fortknox/notallowed"
ALICE = "alice"
AuthorizationNamespace = "authz/image"
AuthorizationAllRepos = "**"
)
func TestVerifyMandatoryAnnotations(t *testing.T) {
//nolint: dupl
Convey("Mandatory annotations disabled", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := false
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
})
//nolint: dupl
Convey("Mandatory annotations enabled, but no list in config", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := true
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
})
Convey("Mandatory annotations verification passing", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := true
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"}
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testPass1"
manifest.Annotations["annotation2"] = "testPass2"
manifest.Annotations["annotation3"] = "testPass3"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
})
Convey("Mandatory annotations verification in manifest and config passing", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := true
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"}
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "annotationPass1"
manifest.Annotations["annotation2"] = "annotationPass2"
configDigest := manifest.Config.Digest
resp, err = resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + fmt.Sprintf("/v2/zot-test/blobs/%s", configDigest))
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
configBlob := resp.Body()
var imageConfig ispec.Image
err = json.Unmarshal(configBlob, &imageConfig)
So(err, ShouldBeNil)
imageConfig.Config.Labels = make(map[string]string)
imageConfig.Config.Labels["annotation3"] = "annotationPass3"
configContent, err := json.Marshal(imageConfig)
So(err, ShouldBeNil)
configBlobDigestRaw := godigest.FromBytes(configContent)
manifest.Config.Digest = configBlobDigestRaw
manifest.Config.Size = int64(len(configContent))
manifestContent, err := json.Marshal(manifest)
So(err, ShouldBeNil)
// upload image config blob
resp, err = resty.R().
Post(fmt.Sprintf("%s/v2/zot-test/blobs/uploads/", baseURL))
So(err, ShouldBeNil)
loc := test.Location(baseURL, resp)
_, err = resty.R().
SetContentLength(true).
SetHeader("Content-Length", fmt.Sprintf("%d", len(configContent))).
SetHeader("Content-Type", "application/octet-stream").
SetQueryParam("digest", configBlobDigestRaw.String()).
SetBody(configContent).
Put(loc)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(manifestContent).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
})
Convey("Mandatory annotations verification in manifest and config failing", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := true
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"}
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testFail1"
configDigest := manifest.Config.Digest
resp, err = resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + fmt.Sprintf("/v2/zot-test/blobs/%s", configDigest))
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
configBlob := resp.Body()
var imageConfig ispec.Image
err = json.Unmarshal(configBlob, &imageConfig)
So(err, ShouldBeNil)
imageConfig.Config.Labels = make(map[string]string)
imageConfig.Config.Labels["annotation2"] = "testFail2"
configContent, err := json.Marshal(imageConfig)
So(err, ShouldBeNil)
configBlobDigestRaw := godigest.FromBytes(configContent)
manifest.Config.Digest = configBlobDigestRaw
manifest.Config.Size = int64(len(configContent))
manifestContent, err := json.Marshal(manifest)
So(err, ShouldBeNil)
// upload image config blob
_, err = resty.R().
Post(fmt.Sprintf("%s/v2/zot-test/blobs/uploads/", baseURL))
So(err, ShouldBeNil)
loc := test.Location(baseURL, resp)
_, err = resty.R().
SetContentLength(true).
SetHeader("Content-Length", fmt.Sprintf("%d", len(configContent))).
SetHeader("Content-Type", "application/octet-stream").
SetQueryParam("digest", configBlobDigestRaw.String()).
SetBody(configContent).
Put(loc)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(manifestContent).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest)
})
Convey("Mandatory annotations incomplete in manifest", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := true
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"}
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testFail1"
manifest.Annotations["annotation3"] = "testFail3"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest)
})
Convey("Mandatory annotations verification passing - more annotations than the mandatory list", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
enable := true
conf.Extensions = &extconf.ExtensionConfig{Lint: &extconf.LintConfig{}}
conf.Extensions.Lint.MandatoryAnnotations = []string{}
conf.Extensions.Lint.Enable = &enable
conf.Extensions.Lint.MandatoryAnnotations = []string{"annotation1", "annotation2", "annotation3"}
ctlr := api.NewController(conf)
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, ctlr.Log)
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
files, err := os.ReadDir(dir)
So(err, ShouldBeNil)
t.Log("Files in dir:", dir, ": ", files)
ctlr.Config.Storage.RootDirectory = dir
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
resp, err := resty.R().SetBasicAuth(username, passphrase).
Get(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
manifestBlob := resp.Body()
var manifest ispec.Manifest
err = json.Unmarshal(manifestBlob, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testPassMore1"
manifest.Annotations["annotation2"] = "testPassMore2"
manifest.Annotations["annotation3"] = "testPassMore3"
manifest.Annotations["annotation4"] = "testPassMore4"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
SetBody(content).Put(baseURL + "/v2/zot-test/manifests/0.0.1")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusCreated)
})
}
func TestVerifyMandatoryAnnotationsFunction(t *testing.T) {
Convey("Mandatory annotations disabled", t, func() {
enable := false
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
indexContent, err := imgStore.GetIndexContent("zot-test")
So(err, ShouldBeNil)
err = json.Unmarshal(indexContent, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
pass, err := linter.CheckMandatoryAnnotations("zot-test", manifestDigest, imgStore)
So(err, ShouldBeNil)
So(pass, ShouldBeTrue)
})
Convey("Mandatory annotations enabled, but no list in config", t, func() {
enable := true
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
indexContent, err := imgStore.GetIndexContent("zot-test")
So(err, ShouldBeNil)
err = json.Unmarshal(indexContent, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
pass, err := linter.CheckMandatoryAnnotations("zot-test", manifestDigest, imgStore)
So(err, ShouldBeNil)
So(pass, ShouldBeTrue)
})
Convey("Mandatory annotations verification passing", t, func() {
enable := true
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json"))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
var manifest ispec.Manifest
buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs",
manifestDigest.Algorithm().String(), manifestDigest.Encoded()))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testPass1"
manifest.Annotations["annotation2"] = "testPass2"
manifest.Annotations["annotation3"] = "testPass3"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
So(content, ShouldNotBeNil)
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, "zot-test", "blobs",
digest.Algorithm().String(), digest.Encoded()), content, 0o600)
So(err, ShouldBeNil)
manifestDesc := ispec.Descriptor{
Size: int64(len(content)),
Digest: digest,
}
index.Manifests = append(index.Manifests, manifestDesc)
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore)
So(err, ShouldBeNil)
So(pass, ShouldBeTrue)
})
Convey("Mandatory annotations incomplete in manifest", t, func() {
enable := true
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json"))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
var manifest ispec.Manifest
buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs",
manifestDigest.Algorithm().String(), manifestDigest.Encoded()))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "test1"
manifest.Annotations["annotation3"] = "test3"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
So(content, ShouldNotBeNil)
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, "zot-test", "blobs",
digest.Algorithm().String(), digest.Encoded()), content, 0o600)
So(err, ShouldBeNil)
manifestDesc := ispec.Descriptor{
Size: int64(len(content)),
Digest: digest,
}
index.Manifests = append(index.Manifests, manifestDesc)
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore)
So(err, ShouldNotBeNil)
So(pass, ShouldBeFalse)
})
Convey("Mandatory annotations verification passing - more annotations than the mandatory list", t, func() {
enable := true
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json"))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
var manifest ispec.Manifest
buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs",
manifestDigest.Algorithm().String(), manifestDigest.Encoded()))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testPassMore1"
manifest.Annotations["annotation2"] = "testPassMore2"
manifest.Annotations["annotation3"] = "testPassMore3"
manifest.Annotations["annotation4"] = "testPassMore4"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
So(content, ShouldNotBeNil)
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, "zot-test", "blobs",
digest.Algorithm().String(), digest.Encoded()), content, 0o600)
So(err, ShouldBeNil)
manifestDesc := ispec.Descriptor{
Size: int64(len(content)),
Digest: digest,
}
index.Manifests = append(index.Manifests, manifestDesc)
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore)
So(err, ShouldBeNil)
So(pass, ShouldBeTrue)
})
Convey("Cannot unmarshal manifest", t, func() {
enable := true
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json"))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
var manifest ispec.Manifest
buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs",
manifestDigest.Algorithm().String(), manifestDigest.Encoded()))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testUnmarshal1"
manifest.Annotations["annotation2"] = "testUnmarshal2"
manifest.Annotations["annotation3"] = "testUnmarshal3"
manifest.SchemaVersion = 2
content, err := json.Marshal(manifest)
So(err, ShouldBeNil)
So(content, ShouldNotBeNil)
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, "zot-test", "blobs",
digest.Algorithm().String(), digest.Encoded()), content, 0o600)
So(err, ShouldBeNil)
manifestDesc := ispec.Descriptor{
Size: int64(len(content)),
Digest: digest,
}
index.Manifests = append(index.Manifests, manifestDesc)
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
err = os.Chmod(path.Join(dir, "zot-test", "blobs"), 0o000)
if err != nil {
panic(err)
}
pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore)
So(err, ShouldNotBeNil)
So(pass, ShouldBeFalse)
err = os.Chmod(path.Join(dir, "zot-test", "blobs"), 0o755)
if err != nil {
panic(err)
}
})
Convey("Cannot get config file", t, func() {
enable := true
lintConfig := &extconf.LintConfig{
BaseConfig: extconf.BaseConfig{Enable: &enable},
MandatoryAnnotations: []string{"annotation1", "annotation2", "annotation3"},
}
dir := t.TempDir()
testStoreCtlr := test.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err := test.WriteImageToFileSystem(test.CreateRandomImage(), "zot-test", "0.0.1", testStoreCtlr)
So(err, ShouldBeNil)
var index ispec.Index
buf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json"))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &index)
So(err, ShouldBeNil)
manifestDigest := index.Manifests[0].Digest
var manifest ispec.Manifest
buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs",
manifestDigest.Algorithm().String(), manifestDigest.Encoded()))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &manifest)
So(err, ShouldBeNil)
manifest.Annotations = make(map[string]string)
manifest.Annotations["annotation1"] = "testAnnotation1"
manifest.Annotations["annotation2"] = "testAnnotation2"
// write config
var imageConfig ispec.Image
configDigest := manifest.Config.Digest
buf, err = os.ReadFile(path.Join(dir, "zot-test", "blobs", "sha256",
configDigest.Encoded()))
So(err, ShouldBeNil)
err = json.Unmarshal(buf, &imageConfig)
So(err, ShouldBeNil)
imageConfig.Config.Labels = make(map[string]string)
imageConfig.Config.Labels["annotation3"] = "testAnnotation3"
configContent, err := json.Marshal(imageConfig)
So(err, ShouldBeNil)
So(configContent, ShouldNotBeNil)
cfgDigest := godigest.FromBytes(configContent)
So(cfgDigest, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, "zot-test", "blobs", "sha256",
cfgDigest.Encoded()), configContent, 0o600)
So(err, ShouldBeNil)
// write manifest
manifest.SchemaVersion = 2
manifest.Config.Size = int64(len(configContent))
manifest.Config.Digest = cfgDigest
manifestContent, err := json.Marshal(manifest)
So(err, ShouldBeNil)
So(manifestContent, ShouldNotBeNil)
digest := godigest.FromBytes(manifestContent)
So(digest, ShouldNotBeNil)
err = os.WriteFile(path.Join(dir, "zot-test", "blobs",
digest.Algorithm().String(), digest.Encoded()), manifestContent, 0o600)
So(err, ShouldBeNil)
manifestDesc := ispec.Descriptor{
Size: int64(len(manifestContent)),
Digest: digest,
}
index.Manifests = append(index.Manifests, manifestDesc)
linter := lint.NewLinter(lintConfig, log.NewLogger("debug", ""))
imgStore := local.NewImageStore(dir, false, false, 0, 0, false, false,
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), linter, nil)
err = os.Chmod(path.Join(dir, "zot-test", "blobs", "sha256", manifest.Config.Digest.Encoded()), 0o000)
if err != nil {
panic(err)
}
pass, err := linter.CheckMandatoryAnnotations("zot-test", digest, imgStore)
So(err, ShouldNotBeNil)
So(pass, ShouldBeFalse)
err = os.Chmod(path.Join(dir, "zot-test", "blobs", "sha256", manifest.Config.Digest.Encoded()), 0o755)
if err != nil {
panic(err)
}
pass, err = linter.CheckMandatoryAnnotations("zot-test", digest, imgStore)
So(err, ShouldBeNil)
So(pass, ShouldBeTrue)
})
}