Check media types when unmarshalling manifests

When unmarshalling manifests from JSON, check that the MediaType field
corresponds to the type that we are unmarshalling as. This makes sure
that when we retrieve a manifest from the manifest store, it will have
the same type as it was handled as before storing it in the manifest
store.

Signed-off-by: Owen W. Taylor <otaylor@fishsoup.net>
This commit is contained in:
Owen W. Taylor 2018-03-14 16:55:45 -04:00
parent f6224f78ba
commit 1d47ef7b80
6 changed files with 214 additions and 17 deletions

View file

@ -38,6 +38,13 @@ func init() {
return nil, distribution.Descriptor{}, err
}
if m.MediaType != MediaTypeManifestList {
err = fmt.Errorf("mediaType in manifest list should be '%s' not '%s'",
MediaTypeManifestList, m.MediaType)
return nil, distribution.Descriptor{}, err
}
dgst := digest.FromBytes(b)
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: MediaTypeManifestList}, err
}
@ -53,6 +60,13 @@ func init() {
return nil, distribution.Descriptor{}, err
}
if m.MediaType != v1.MediaTypeImageIndex {
err = fmt.Errorf("mediaType in image index should be '%s' not '%s'",
v1.MediaTypeImageIndex, m.MediaType)
return nil, distribution.Descriptor{}, err
}
dgst := digest.FromBytes(b)
return m, distribution.Descriptor{Digest: dgst, Size: int64(len(b)), MediaType: v1.MediaTypeImageIndex}, err
}
@ -130,15 +144,23 @@ type DeserializedManifestList struct {
// DeserializedManifestList which contains the resulting manifest list
// and its JSON representation.
func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedManifestList, error) {
var m ManifestList
var mediaType string
if len(descriptors) > 0 && descriptors[0].Descriptor.MediaType == v1.MediaTypeImageManifest {
m = ManifestList{
Versioned: OCISchemaVersion,
}
mediaType = v1.MediaTypeImageIndex
} else {
m = ManifestList{
Versioned: SchemaVersion,
}
mediaType = MediaTypeManifestList
}
return FromDescriptorsWithMediaType(descriptors, mediaType)
}
// For testing purposes, it's useful to be able to specify the media type explicitly
func FromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType string) (*DeserializedManifestList, error) {
m := ManifestList{
Versioned: manifest.Versioned{
SchemaVersion: 2,
MediaType: mediaType,
},
}
m.Manifests = make([]ManifestDescriptor, len(descriptors), len(descriptors))

View file

@ -38,7 +38,7 @@ var expectedManifestListSerialization = []byte(`{
]
}`)
func TestManifestList(t *testing.T) {
func makeTestManifestList(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedManifestList) {
manifestDescriptors := []ManifestDescriptor{
{
Descriptor: distribution.Descriptor{
@ -65,11 +65,16 @@ func TestManifestList(t *testing.T) {
},
}
deserialized, err := FromDescriptors(manifestDescriptors)
deserialized, err := FromDescriptorsWithMediaType(manifestDescriptors, mediaType)
if err != nil {
t.Fatalf("error creating DeserializedManifestList: %v", err)
}
return manifestDescriptors, deserialized
}
func TestManifestList(t *testing.T) {
manifestDescriptors, deserialized := makeTestManifestList(t, MediaTypeManifestList)
mediaType, canonical, _ := deserialized.Payload()
if mediaType != MediaTypeManifestList {
@ -160,7 +165,7 @@ var expectedOCIImageIndexSerialization = []byte(`{
]
}`)
func TestOCIImageIndex(t *testing.T) {
func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedManifestList) {
manifestDescriptors := []ManifestDescriptor{
{
Descriptor: distribution.Descriptor{
@ -196,11 +201,17 @@ func TestOCIImageIndex(t *testing.T) {
},
}
deserialized, err := FromDescriptors(manifestDescriptors)
deserialized, err := FromDescriptorsWithMediaType(manifestDescriptors, mediaType)
if err != nil {
t.Fatalf("error creating DeserializedManifestList: %v", err)
}
return manifestDescriptors, deserialized
}
func TestOCIImageIndex(t *testing.T) {
manifestDescriptors, deserialized := makeTestOCIImageIndex(t, v1.MediaTypeImageIndex)
mediaType, canonical, _ := deserialized.Payload()
if mediaType != v1.MediaTypeImageIndex {
@ -241,3 +252,54 @@ func TestOCIImageIndex(t *testing.T) {
}
}
}
func mediaTypeTest(t *testing.T, contentType string, mediaType string, shouldError bool) {
var m *DeserializedManifestList
if contentType == MediaTypeManifestList {
_, m = makeTestManifestList(t, mediaType)
} else {
_, m = makeTestOCIImageIndex(t, mediaType)
}
_, canonical, err := m.Payload()
if err != nil {
t.Fatalf("error getting payload, %v", err)
}
unmarshalled, descriptor, err := distribution.UnmarshalManifest(
contentType,
canonical)
if shouldError {
if err == nil {
t.Fatalf("bad content type should have produced error")
}
} else {
if err != nil {
t.Fatalf("error unmarshaling manifest, %v", err)
}
asManifest := unmarshalled.(*DeserializedManifestList)
if asManifest.MediaType != mediaType {
t.Fatalf("Bad media type '%v' as unmarshalled", asManifest.MediaType)
}
if descriptor.MediaType != contentType {
t.Fatalf("Bad media type '%v' for descriptor", descriptor.MediaType)
}
unmarshalledMediaType, _, _ := unmarshalled.Payload()
if unmarshalledMediaType != contentType {
t.Fatalf("Bad media type '%v' for payload", unmarshalledMediaType)
}
}
}
func TestMediaTypes(t *testing.T) {
mediaTypeTest(t, MediaTypeManifestList, "", true)
mediaTypeTest(t, MediaTypeManifestList, MediaTypeManifestList, false)
mediaTypeTest(t, MediaTypeManifestList, MediaTypeManifestList+"XXX", true)
mediaTypeTest(t, v1.MediaTypeImageIndex, "", true)
mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex, false)
mediaTypeTest(t, v1.MediaTypeImageIndex, v1.MediaTypeImageIndex+"XXX", true)
}