From bcb75b07e5dd1426c1e1a86b53de94c928e7cddd Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 5 Nov 2016 15:12:00 -0700 Subject: [PATCH 1/2] descriptor: Require RFC-6838-compliant mediaTypes Restore the MUST which was removed from the 15f9f741 version of this commit. My personal preference would be to just say: Values MUST comply with [RFC 6838][rfc6838]. But Stephen wanted a direct reference to 4.2 as well [1]. [1]: https://github.com/opencontainers/image-spec/pull/448#discussion_r97862790 Signed-off-by: W. Trevor King --- descriptor.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/descriptor.md b/descriptor.md index f14d7cb48..4bc5e0414 100644 --- a/descriptor.md +++ b/descriptor.md @@ -19,7 +19,8 @@ The following fields contain the primary properties that constitute a Descriptor - **`mediaType`** *string* - This REQUIRED property contains the MIME type of the referenced content. + This REQUIRED property contains the media type of the referenced content. + Values MUST comply with [RFC 6838][rfc6838], including the [naming requirements in its section 4.2][rfc6838-s4.2]. The OCI image specification defines [several of its own MIME types](media-types.md) for resources defined in the specification. @@ -139,4 +140,6 @@ In the following example, the descriptor indicates that the referenced manifest ``` [rfc3986]: https://tools.ietf.org/html/rfc3986 +[rfc6838]: https://tools.ietf.org/html/rfc6838 +[rfc6838-s4.2]: https://tools.ietf.org/html/rfc6838#section-4.2 [rfc7230-s2.7]: https://tools.ietf.org/html/rfc7230#section-2.7 From be553fb4e5aed50de618b11c6fc6443219e635bb Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 5 Nov 2016 15:39:21 -0700 Subject: [PATCH 2/2] schema/descriptor_test: Add descriptor tests Working these up turned up a few bugs in the old schema, which we've fixed in the earlier commits in this series. Signed-off-by: W. Trevor King --- schema/descriptor_test.go | 213 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 schema/descriptor_test.go diff --git a/schema/descriptor_test.go b/schema/descriptor_test.go new file mode 100644 index 000000000..68c35cead --- /dev/null +++ b/schema/descriptor_test.go @@ -0,0 +1,213 @@ +// Copyright 2016 The Linux Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package schema_test + +import ( + "strings" + "testing" + + "github.com/opencontainers/image-spec/schema" +) + +func TestDescriptor(t *testing.T) { + for i, tt := range []struct { + descriptor string + fail bool + }{ + // valid descriptor + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: false, + }, + + // expected failure: mediaType missing + { + descriptor: ` +{ + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: mediaType does not match pattern (no subtype) + { + descriptor: ` +{ + "mediaType": "application", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: mediaType does not match pattern (invalid first type character) + { + descriptor: ` +{ + "mediaType": ".foo/bar", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: mediaType does not match pattern (invalid first subtype character) + { + descriptor: ` +{ + "mediaType": "foo/.bar", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected success: mediaType has type and subtype as long as possible + { + descriptor: ` +{ + "mediaType": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567/1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: false, + }, + + // expected success: mediaType does not match pattern (type too long) + { + descriptor: ` +{ + "mediaType": "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678/bar", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected success: mediaType does not match pattern (subtype too long) + { + descriptor: ` +{ + "mediaType": "foo/12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: size missing + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: size is a string, expected integer + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": "7682", + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: digest missing + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682 +} +`, + fail: true, + }, + + // expected failure: digest does not match pattern (no algorithm) + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682, + "digest": ":5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: digest does not match pattern (no hash) + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682, + "digest": "sha256" +} +`, + fail: true, + }, + + // expected failure: digest does not match pattern (invalid aglorithm characters) + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682, + "digest": "SHA256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, + fail: true, + }, + + // expected failure: digest does not match pattern (invalid hash characters) + { + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682, + "digest": "sha256:5B0BCABD1ED22E9FB1310CF6C2DEC7CDEF19F0AD69EFA1F392E94A4333501270" +} +`, + fail: true, + }, + } { + r := strings.NewReader(tt.descriptor) + err := schema.MediaTypeDescriptor.Validate(r) + + if got := err != nil; tt.fail != got { + t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err) + } + } +}