0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2025-03-18 02:22:53 -05:00

fix: MetaDB fixes related to Docker media types ()

* fix: update download counters for docker media types

closes 

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

* fix: handle docker config mediatype in MetaDB

The OS/Arch/Layer History information was not written to MetaDB

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>

---------

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
This commit is contained in:
Andrei Aaron 2025-02-03 08:29:55 +02:00 committed by GitHub
parent 4fcd1079f7
commit ea6b6dab23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 272 additions and 3 deletions
pkg
compat
extensions/search
meta

View file

@ -45,6 +45,20 @@ func IsCompatibleManifestListMediaType(mediatype string) bool {
return false
}
func CompatibleConfigMediaTypes() []string {
return []string{docker.MediaTypeImageConfig}
}
func IsCompatibleConfigMediaType(mediatype string) bool {
for _, mt := range CompatibleConfigMediaTypes() {
if mt == mediatype {
return true
}
}
return false
}
func Validate(body []byte, mediaType string) ([]v1.Descriptor, error) {
switch mediaType {
case docker.MediaTypeManifest:

View file

@ -331,7 +331,8 @@ func getConfigAndDigest(metaDB mTypes.MetaDB, manifestDigestStr string) (ispec.I
}
// we'll fail the execution if the config is not compatible with ispec.Image because we can't scan this type of images.
if manifestData.Manifests[0].Manifest.Config.MediaType != ispec.MediaTypeImageConfig {
configMediaType := manifestData.Manifests[0].Manifest.Config.MediaType
if configMediaType != ispec.MediaTypeImageConfig && !compat.IsCompatibleConfigMediaType(configMediaType) {
return ispec.Image{}, "", zerr.ErrUnexpectedMediaType
}

View file

@ -1749,6 +1749,257 @@ func TestExpandedRepoInfo(t *testing.T) {
So(found, ShouldBeTrue)
})
Convey("Test expanded repo info for docker media type", t, func() {
subpath := "/a"
rootDir := t.TempDir()
subRootDir := t.TempDir()
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = rootDir
conf.Storage.GC = false
conf.Storage.SubPaths = make(map[string]config.StorageConfig)
conf.Storage.SubPaths[subpath] = config.StorageConfig{RootDirectory: subRootDir}
defaultVal := true
conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
}
conf.Extensions.Search.CVE = nil
ctlr := api.NewController(conf)
ctlrManager := NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
annotations := make(map[string]string)
annotations["org.opencontainers.image.vendor"] = "zot"
configBlob, err := json.Marshal(GetDefaultConfig())
So(err, ShouldBeNil)
uploadedImage := CreateImageWith().RandomLayers(1, 100).
CustomConfigBlob(configBlob, "application/vnd.docker.container.image.v1+json").
Annotations(annotations).Build()
err = UploadImage(uploadedImage, baseURL, "zot-cve-test", "0.0.1")
So(err, ShouldBeNil)
err = UploadImage(uploadedImage, baseURL, "a/zot-cve-test", "0.0.1")
So(err, ShouldBeNil)
err = UploadImage(uploadedImage, baseURL, "zot-test", "0.0.1")
So(err, ShouldBeNil)
err = UploadImage(uploadedImage, baseURL, "a/zot-test", "0.0.1")
So(err, ShouldBeNil)
log := log.NewLogger("debug", "")
metrics := monitoring.NewMetricsServer(false, log)
testStorage := local.NewImageStore(rootDir, false, false, log, metrics, nil, nil, nil)
resp, err := resty.R().Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix)
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 422)
query := `{
ExpandedRepoInfo(repo:"zot-cve-test"){
Summary {
Name LastUpdated Size
}
}
}`
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
responseStruct := &zcommon.ExpandedRepoInfoResp{}
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
So(responseStruct.Summary, ShouldNotBeEmpty)
So(responseStruct.Summary.Name, ShouldEqual, "zot-cve-test")
query = `{
ExpandedRepoInfo(repo:"zot-cve-test"){
Images {
Tag
Manifests {
Digest
Layers {Size Digest}
Platform {Os Arch}
}
IsSigned
}
}
}`
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
responseStruct = &zcommon.ExpandedRepoInfoResp{}
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
So(len(responseStruct.ImageSummaries), ShouldNotEqual, 0)
So(len(responseStruct.ImageSummaries[0].Manifests[0].Layers), ShouldNotEqual, 0)
_, testManifestDigest, _, err := testStorage.GetImageManifest("zot-cve-test", "0.0.1")
So(err, ShouldBeNil)
found := false
for _, imageSummary := range responseStruct.ImageSummaries {
if imageSummary.Manifests[0].Digest == testManifestDigest.String() {
found = true
So(imageSummary.IsSigned, ShouldEqual, false)
So(imageSummary.Manifests[0].Platform.Os, ShouldEqual, "linux")
So(imageSummary.Manifests[0].Platform.Arch, ShouldEqual, "amd64")
}
}
So(found, ShouldEqual, true)
err = signature.SignImageUsingCosign("zot-cve-test:0.0.1", port, false)
So(err, ShouldBeNil)
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
So(len(responseStruct.ImageSummaries), ShouldNotEqual, 0)
So(len(responseStruct.ImageSummaries[0].Manifests[0].Layers), ShouldNotEqual, 0)
_, testManifestDigest, _, err = testStorage.GetImageManifest("zot-cve-test", "0.0.1")
So(err, ShouldBeNil)
found = false
for _, imageSummary := range responseStruct.ImageSummaries {
if imageSummary.Manifests[0].Digest == testManifestDigest.String() {
found = true
So(imageSummary.IsSigned, ShouldEqual, true)
So(imageSummary.Manifests[0].Platform.Os, ShouldEqual, "linux")
So(imageSummary.Manifests[0].Platform.Arch, ShouldEqual, "amd64")
}
}
So(found, ShouldEqual, true)
query = `{
ExpandedRepoInfo(repo:""){
Images {
Tag
}
}
}`
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
query = `{
ExpandedRepoInfo(repo:"zot-test"){
Images {
RepoName
Tag IsSigned
Manifests{
Digest
Layers {Size Digest}
Platform {Os Arch}
}
}
}
}`
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
So(len(responseStruct.ImageSummaries), ShouldNotEqual, 0)
So(len(responseStruct.ImageSummaries[0].Manifests[0].Layers), ShouldNotEqual, 0)
_, testManifestDigest, _, err = testStorage.GetImageManifest("zot-test", "0.0.1")
So(err, ShouldBeNil)
found = false
for _, imageSummary := range responseStruct.ImageSummaries {
if imageSummary.Manifests[0].Digest == testManifestDigest.String() {
found = true
So(imageSummary.IsSigned, ShouldEqual, false)
So(imageSummary.Manifests[0].Platform.Os, ShouldEqual, "linux")
So(imageSummary.Manifests[0].Platform.Arch, ShouldEqual, "amd64")
}
}
So(found, ShouldEqual, true)
err = signature.SignImageUsingCosign("zot-test@"+testManifestDigest.String(), port, false)
So(err, ShouldBeNil)
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "/query?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
So(len(responseStruct.ImageSummaries), ShouldNotEqual, 0)
So(len(responseStruct.ImageSummaries[0].Manifests[0].Layers), ShouldNotEqual, 0)
_, testManifestDigest, _, err = testStorage.GetImageManifest("zot-test", "0.0.1")
So(err, ShouldBeNil)
found = false
for _, imageSummary := range responseStruct.ImageSummaries {
if imageSummary.Manifests[0].Digest == testManifestDigest.String() {
found = true
So(imageSummary.IsSigned, ShouldEqual, true)
So(imageSummary.Manifests[0].Platform.Os, ShouldEqual, "linux")
So(imageSummary.Manifests[0].Platform.Arch, ShouldEqual, "amd64")
}
}
So(found, ShouldEqual, true)
manifestDigest := uploadedImage.ManifestDescriptor.Digest
err = os.Remove(path.Join(rootDir, "zot-test/blobs/sha256", manifestDigest.Encoded()))
So(err, ShouldBeNil)
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
})
}
func TestDerivedImageList(t *testing.T) {

View file

@ -7,6 +7,7 @@ import (
v1 "github.com/opencontainers/image-spec/specs-go/v1"
zcommon "zotregistry.dev/zot/pkg/common"
"zotregistry.dev/zot/pkg/compat"
"zotregistry.dev/zot/pkg/log"
mTypes "zotregistry.dev/zot/pkg/meta/types"
"zotregistry.dev/zot/pkg/storage"
@ -117,7 +118,8 @@ func OnGetManifest(name, reference, mediaType string, body []byte,
return nil
}
if !(mediaType == v1.MediaTypeImageManifest || mediaType == v1.MediaTypeImageIndex) {
if !(mediaType == v1.MediaTypeImageManifest || mediaType == v1.MediaTypeImageIndex ||
compat.IsCompatibleManifestMediaType(mediaType) || compat.IsCompatibleManifestListMediaType(mediaType)) {
return nil
}

View file

@ -321,7 +321,8 @@ func SetImageMetaFromInput(ctx context.Context, repo, reference, mediaType strin
return err
}
if manifestContent.Config.MediaType == ispec.MediaTypeImageConfig {
if manifestContent.Config.MediaType == ispec.MediaTypeImageConfig ||
compat.IsCompatibleConfigMediaType(manifestContent.Config.MediaType) {
configBlob, err := imageStore.GetBlobContent(repo, manifestContent.Config.Digest)
if err != nil {
return err