feat: add additional manifest validations (#1609)

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
peusebiu
2023-07-13 19:31:39 +03:00
committed by GitHub
parent 730ef4aada
commit d3f27b4ba6
14 changed files with 626 additions and 85 deletions
+15
View File
@@ -51,6 +51,7 @@ import (
zerr "zotregistry.io/zot/errors"
"zotregistry.io/zot/pkg/meta/repodb"
"zotregistry.io/zot/pkg/storage"
storageCommon "zotregistry.io/zot/pkg/storage/common"
"zotregistry.io/zot/pkg/test/inject"
)
@@ -1020,6 +1021,11 @@ func UploadImage(img Image, baseURL, repo string) error {
return err
}
// validate manifest
if err := storageCommon.ValidateManifestSchema(manifestBlob); err != nil {
return err
}
if img.Reference == "" {
img.Reference = godigest.FromBytes(manifestBlob).String()
}
@@ -1886,6 +1892,8 @@ func GetRandomMultiarchImage(reference string) (MultiarchImage, error) {
return MultiarchImage{}, err
}
index.SchemaVersion = 2
return MultiarchImage{
Index: index, Images: images, Reference: reference,
}, err
@@ -1905,6 +1913,8 @@ func GetMultiarchImageForImages(reference string, images []Image) MultiarchImage
images[i].Reference = getManifestDigest(image.Manifest).String()
}
index.SchemaVersion = 2
return MultiarchImage{Index: index, Images: images, Reference: reference}
}
@@ -1940,6 +1950,11 @@ func UploadMultiarchImage(multiImage MultiarchImage, baseURL string, repo string
return err
}
// validate manifest
if err := storageCommon.ValidateImageIndexSchema(indexBlob); err != nil {
return err
}
resp, err := resty.R().
SetHeader("Content-type", ispec.MediaTypeImageIndex).
SetBody(indexBlob).
+132
View File
@@ -16,6 +16,7 @@ import (
notconfig "github.com/notaryproject/notation-go/config"
godigest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
"golang.org/x/crypto/bcrypt"
@@ -377,7 +378,125 @@ func TestUploadBlob(t *testing.T) {
})
}
func TestUploadMultiarchImage(t *testing.T) {
Convey("make controller", 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,
},
Manifest: ispec.Manifest{
Versioned: specs.Versioned{
SchemaVersion: 2,
},
Layers: []ispec.Descriptor{
{
Digest: godigest.FromBytes(layerBlob),
Size: int64(len(layerBlob)),
MediaType: ispec.MediaTypeImageLayerGzip,
},
},
Config: ispec.DescriptorEmptyJSON,
},
Config: ispec.Image{},
}
manifestBuf, err := json.Marshal(img.Manifest)
So(err, ShouldBeNil)
Convey("Multiarch image uploaded successfully", func() {
err = test.UploadMultiarchImage(test.MultiarchImage{
Index: ispec.Index{
Versioned: specs.Versioned{
SchemaVersion: 2,
},
MediaType: ispec.MediaTypeImageIndex,
Manifests: []ispec.Descriptor{
{
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromBytes(manifestBuf),
Size: int64(len(manifestBuf)),
},
},
},
Images: []test.Image{img},
Reference: "index",
}, baseURL, "test")
So(err, ShouldBeNil)
})
Convey("Multiarch image without schemaVersion should fail validation", func() {
err = test.UploadMultiarchImage(test.MultiarchImage{
Index: ispec.Index{
MediaType: ispec.MediaTypeImageIndex,
Manifests: []ispec.Descriptor{
{
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromBytes(manifestBuf),
Size: int64(len(manifestBuf)),
},
},
},
Images: []test.Image{img},
Reference: "index",
}, baseURL, "test")
So(err, ShouldNotBeNil)
})
})
}
func TestUploadImage(t *testing.T) {
Convey("Manifest without schemaVersion should fail validation", 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,
},
Manifest: ispec.Manifest{
Layers: []ispec.Descriptor{
{
Digest: godigest.FromBytes(layerBlob),
Size: int64(len(layerBlob)),
MediaType: ispec.MediaTypeImageLayerGzip,
},
},
Config: ispec.DescriptorEmptyJSON,
},
Config: ispec.Image{},
}
err := test.UploadImage(img, baseURL, "test")
So(err, ShouldNotBeNil)
})
Convey("Post request results in an error", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
@@ -465,6 +584,19 @@ func TestUploadImage(t *testing.T) {
Layers: [][]byte{
layerBlob,
},
Manifest: ispec.Manifest{
Versioned: specs.Versioned{
SchemaVersion: 2,
},
Layers: []ispec.Descriptor{
{
Digest: godigest.FromBytes(layerBlob),
Size: int64(len(layerBlob)),
MediaType: ispec.MediaTypeImageLayerGzip,
},
},
Config: ispec.DescriptorEmptyJSON,
},
Config: ispec.Image{},
}