Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spec: describe descriptors and digests #111

Merged
merged 2 commits into from
Jun 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions descriptor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# OpenContainers Content Descriptors

OCI have several components that come to together to describe an image.
References between components form a [Merkle Directed Acyclic Graph (DAG)](https://en.wikipedia.org/wiki/Merkle_tree).
The references in the _Merkle DAG_ are expressed through _Content Descriptors_.
A _Content Descriptor_ or _Descriptor_, describes the disposition of targeted content.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disposition? seems like an ambiguous word here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"disposition" precisely means "the way in which something is placed or arranged, especially in relation to other things".

However, "describes the disposition" stutters, as well. I'll tweak this. Any suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Fri, Jun 03, 2016 at 11:38:09AM -0700, Stephen Day wrote:

+The references in the Merkle DAG are expressed through Content Descriptors.
+A Content Descriptor or Descriptor, describes the disposition of targeted content.

"disposition" precisely means "the way in which something is placed
or arranged, especially in relation to other things".

However, "describes the disposition" stutters, as well. I'll tweak
this. Any suggestions?

I'd just drop the line. The previous line and rest of the docs make
the idea clear enough.

A _Descriptor_ includes the type of content, an independently-verifiable content identifier, known as a "digest" and the byte-size of the raw content.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “, known as a "digest"” bit makes the three-part content listing hard for me to read. Can we drop this sentence, since we have a detailed “Properties” section below?


Descriptors SHOULD be embedded in other formats to securely reference external content.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be turned around to get “Other formats SHOULD use descriptors to securely reference external content”.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on turning it around as this format will stand on its own in #94

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, +1 on this change but I see below it says they can be independent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Wed, Jun 01, 2016 at 04:59:36PM -0700, Brandon Philips wrote:

+Descriptors SHOULD be embedded in other formats to securely reference external content.

Well, +1 on this change but I see below it says they can be independent

We got the turned-around “Other formats SHOULD use descriptors to
securely reference external content.” line, but this is still here.
Can we drop this line?


Other formats SHOULD use descriptors to securely reference external content.

## Properties

The following describe the primary set of properties that make up a _Descriptor_.

- **`mediaType`** *string*

This REQUIRED property contains the MIME type of the referenced object.

- **`digest`** *string*

This REQUIRED property is the _digest_ of the targeted content, meeting the requirements outlined in [Digests and Verification](#digests-and—verification).
Retrieved content SHOULD be verified against this digest when consumed via untrusted sources.

- **`size`** *int*
This REQUIRED property specifies the size in bytes of the blob.
This property exists so that a client will have an expected size for the content before validating.
If the length of the retrieved content does not match the specified length, the content SHOULD NOT be trusted.

### Reserved
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@philips @vbatts @wking Do we need to also call out fields that are used by other specs that are included on the descriptor? I think we have platform elsewhere.

It might be sufficient to say we allow extensions of descriptor, but reserve a few (ie, data).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevvooe I don't follow. Are you saying some other type is polymorphic? Which one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, we want to allow extension of descriptors but reserve a set of fields that may not be supplanted by other specifications.

An example is the urls field, which was recently added to descriptor in Docker. We want to reserve definition of the urls field for this specification and not other specifications that may inherit these base properties.

Another example is data, which would may include the content directly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jun 02, 2016 at 01:11:54PM -0700, Stephen Day wrote:

+### Reserved

In general, we want to allow extension of descriptors but reserve a
set of fields that may not be supplanted by other specifications.

cough LSON-LD cough 1 ;).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how JSON-LD is related at all. Seems to be overcomplicated and unfocused in the problems it solves. What benefit do you see in bringing the complexity of XML to JSON?

Do you have examples?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jun 02, 2016 at 02:28:46PM -0700, Stephen Day wrote:

Seems overly complex, when we can just call it out in the
specification.

But that approach requires you (and anyone adding their own fields,
e.g. vendor A and vendor B) to declare, up front, any namespace they
want to claim. While with JSON-LD, you only need to declare the bits
you actually need, and spec-consumers can cleanly mix and match as
they see fit.

And it looks like my vendor example should have been 1:

{
"@context": [
"http://opencontainers.org/image/descriptor/1.0",
{
"urls": "http://example.com/overload/urls"
}
],
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"urls": ["a.example.com"]
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but what problem does this complexity actually solve?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jun 02, 2016 at 02:58:34PM -0700, Stephen Day wrote:

+### Reserved

Sure, but what problem does this complexity actually solve?

You get to drop this section and sleep soundly without wondering if
you should have claimed ‘urls’ (or ‘data’ 1, or …). Vendors can add
their own optimizations without worrying about ambiguous
interpretations. I can put an entry in my manifest saying “if you
don't want to bother with the usual layout, you can find this
directory at /ipfs/QmTkzDw…”, and clients who understand that type can
take advantage of it, while clients who don't can fall back to the
image-spec tarball layers. Clients who are compatible with v1.0 of
the spec can still process v1.1 configs if that config only uses
parameters that were spec'ed in v1.0 (because the v1.1 context will
link the same definitions for those parameters). If you want me to
keep adding to this list, let me know ;).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I could sleep soundly unleashing JSON-LD on implementors.

Either way, this clause wouldn't protect against vendor-added fields in a descriptor. That is simply not supported. If one drops a random field into a descriptor, it may be overwritten by future versions of the specification. We already have annotations to cover this use case.

This statement would only reserve it from use in other OCI specifications that use descriptors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jun 02, 2016 at 03:33:16PM -0700, Stephen Day wrote:

Either way, this clause wouldn't protect against vendor-added fields
in a descriptor. That is simply not supported. If one drops a random
field into a descriptor, it may be overwritten by future versions of
the specification.

That is supported by JSON-LD. Here's how you use both at once:

{
"@context": [
"http://opencontainers.org/image/descriptor/1.0",
{
"vendorUrls": "http://example.com/overload/urls"
}
],
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"urls": [
"https://a.example.com/cas",
"https://b.example.com/blobs"
],
"vendorUrls": ["a.example.com"]
}

With JSON-LD, the property name (e.g. ‘urls’, ‘vendorUrls’, …) isn't
the semantic identifier; it's just a link to the @context entry where
you assign semantic IRIs
(e.g. ‘http://opencontainers.org/image/descriptor/urls’,
http://example.com/overload/urls’, …)


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why are these reserved? I'm surprising unclear on this. Is it because docker is using them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docker is introducing a urls field in moby/moby#22866 and it is already part of the latest manifest specification. We have not yet pushed it in OCI since we are unsure of the correct considerations in practice, but it should be introduced.

data is reserved for possibly directly embedding the binary data for a resource, avoiding a fetch. We haven't found a convincing use case, but we should hold it here for consideration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right on. Maybe there could be a notion of scoping? docker.urls or x.urls?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there could be a notion of scoping? docker.urls or x.urls?

Namespacing is a solid option, as is allowing annotations, but we really need to balance this against the simplicity and compatibility of descriptors.

The manifest list descriptor uses platform as an extension, over the more flexible labels approach. I suspect that these kind of "curated extensions" are best for cross-vendor compatibility.

Either way, let's see how urls support pans out in Docker and work from there. 👀

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine leaving these as reserved. Honestly, I would rather just define them here first but reserving more stuff rather than less in the interest of caution is fine.

Overtime, my hope is that whatever discussion lead to urls being added to the Docker media type happens in OCI post-v1.0 as we all focus on a single shared spec.

The following are field keys that MUST NOT be used in descriptors specified in other OCI specifications:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're restricting your reservation to “other OCI specifications”? I expect you can trust OCI maintainers to PR this spec if they want a new descriptor field. The folks you want to warn off are external implementations and specs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And because it doesn't hurt to also warn off other OCI specs, I'd use something generic like “MUST NOT be defined outside this specificiation”.


- **`urls`** *array*

This key is RESERVED for future versions of the specification.

- **`data`** *string*

This key is RESERVED for futures versions of the specification.

All other fields may be included in other OCI specifications.
Extended _Descriptor_ field additions proposed in other OCI specifications SHOULD first be considered for addition into this specification.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd drop OCI from both of these lines.


## Digests and Verification

The _digest_ component of a _Descriptor_ acts as a content identifier, employing [content addressability](http://en.wikipedia.org/wiki/Content-addressable_storage) for the OCI image format.
It uniquely identifies content by taking a collision-resistant hash of the bytes.
Such an identifier can be independently calculated and verified by selection of a common _algorithm_.
If such an identifier can be communicated in a secure manner, one can retrieve the content from an insecure source, calculate it independently and be certain that the correct content was obtained.
Put simply, the identifier is a property of the content.

To disambiguate from other concepts, we call this identifier a _digest_.
A _digest_ is a serialized hash result, consisting of a _algorithm_ and _hex_ portion.
The _algorithm_ identifies the methodology used to calculate the digest, which are shared by implementations.
The _hex_ portion is the hex-encoded result of the hash.

We define a _digest_ string to match the following grammar:

```
digest := algorithm ":" hex
algorithm := /[A-Fa-f0-9_+.-]+/
hex := /[A-Fa-f0-9]+/
```

Some examples of _digests_ include the following:

digest | description |
----------------------------------------------------------------------------------|------------------------------------------------
sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b | Common sha256 based digest |

Before consuming content targeted by a descriptor from untrusted sources, the byte content SHOULD be verified against the _digest_.
The size of the content SHOULD be verified to reduce hash collision space.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This (and the <!--[metadata]…--> removal) should have probably been squashed into the previous commit. Or maybe make the whole branch a single commit?

Heavy processing of before calculating a hash SHOULD be avoided.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“processing of before” → “processing before”. And maybe explain that this suggestion is denial-of-service protection.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Implementations MAY employ some canonicalization to ensure stable content identifiers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This content-production suggestion seems out-of-scope for a digest spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fairly important consideration when building content-addressable systems. This is saying the practice is acceptable but discouraged.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Wed, Jun 01, 2016 at 04:37:46PM -0700, Stephen Day wrote:

+Implementations MAY employ some canonicalization to ensure stable
content identifiers.

This is a fairly important consideration when building
content-addressable systems. This is saying the practice is
acceptable but discouraged.

Wait why discouraged? I think it's a good idea. I'm just saying
that blob authors are unlikely to be perusing the descriptor docs for
those kind of hints.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevvooe can you provide a concrete example of canonicalization?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait why discouraged?

Processing unverified content is problematic. For example, one should not process canonicalize a tar file before calculating the content digest. If this is done, it should only be done on the generation side.

I'll add some language here to clear that up.

I'm just saying
that blob authors are unlikely to be perusing the descriptor docs for
those kind of hints.

And that will likely result in hash stability problems.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Wed, Jun 01, 2016 at 05:04:43PM -0700, Stephen Day wrote:

I'm just saying that blob authors are unlikely to be perusing the
descriptor docs for those kind of hints.

And that will likely result in hash stability problems.

We should definitely be talking about hash stability in image-spec,
just not in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevvooe can you provide a concrete example of canonicalization?

In the spec or in response to your comment?


Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include mention of size verification to avoid Length Extension Attack.

### Algorithms

While the _algorithm_ does allow one to implement a wide variety of algorithms, compliant implementations SHOULD use [SHA-256](#SHA-256).

Let's use a simple example in pseudo-code to demonstrate a digest calculation:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is generic “Digests and Verification” stuff, so I think we should move it out of the “Algorithms” subsection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to clarify the algorithm for using H to get a digest from C.

A _digest_ is calculated by the following pseudo-code, where `H` is the selected hash algorithm, identified by string `<alg>`:
```
let ID(C) = Descriptor.digest
let C = <bytes>
let D = '<alg>:' + EncodeHex(H(C))
let verified = ID(C) == D
```
Above, we define the content identifier as `ID(C)`, extracted from the `Descriptor.digest` field.
Content `C` is a string of bytes.
Function `H` returns a the hashs of `C` in bytes and is passed to function `EncodeHex` to obtain the _digest_.
The result `verified` is true if `ID(C)` is equal to `D`, confirming that `C` is the content identified by `D`.
After verification, the following is true:

```
D == ID(C) == '<alg>:' + EncodeHex(H(C))
```

The _digest_ is confirmed as the content identifier by independently calculating the _digest_.

#### SHA-256

[SHA-256](https://tools.ietf.org/html/rfc4634#page-7) is a collision-resistant hash function, chosen for ubiquity, reasonable size and secure characteristics.
Implementations MUST implement SHA-256 digest verification for use in descriptors.

## Examples

The following example describes a [_Manifest_](manifest.md#image-manifest) with a content identifier of "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270", of size 7682 bytes:

```json,title=Content%20Descriptor&mediatype=application/vnd.oci.descriptor.v1%2Bjson
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270"
}
```
1 change: 1 addition & 0 deletions media-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

The following `mediaType` MIME types are used by the formats described here, and the resources they reference:

- `application/vnd.oci.descriptor.v1+json`: [Content Descriptor](descriptor.md)
- `application/vnd.oci.image.manifest.list.v1+json`: [Manifest list](manifest.md#manifest-list)
- `application/vnd.oci.image.manifest.v1+json`: [Image manifest format](manifest.md#image-manifest)
- `application/vnd.oci.image.serialization.rootfs.tar.gzip`: ["Layer", as a gzipped tar archive](serialization.md#creating-an-image-filesystem-changeset)
Expand Down
24 changes: 24 additions & 0 deletions schema/content-descriptor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"description": "OpenContainer Content Descriptor Specification",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://opencontainers.org/schema/descriptor",
"type": "object",
"properties": {
"mediaType": {
"description": "the mediatype of the referenced object",
"$ref": "defs-image.json#definitions/mediaType"
},
"size": {
"description": "the size in bytes of the referenced object",
"type": "integer"
},
"digest": {
"$ref": "defs-image.json#definitions/digest"
}
},
"required": [
"mediaType",
"size",
"digest"
]
}
22 changes: 0 additions & 22 deletions schema/defs-image.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,6 @@
"type": "string",
"pattern": "^[a-z0-9]+:[a-fA-F0-9]+$"
},
"descriptor": {
"id": "https://opencontainers.org/schema/image/descriptor",
"type": "object",
"required": [
"mediaType",
"size",
"digest"
],
"properties": {
"mediaType": {
"description": "the mediatype of the referenced object",
"$ref": "#definitions/mediaType"
},
"size": {
"description": "the size in bytes of the referenced object",
"type": "integer"
},
"digest": {
"$ref": "#definitions/digest"
}
}
},
"manifestDescriptor": {
"id": "https://opencontainers.org/schema/image/manifestDescriptor",
"type": "object",
Expand Down
65 changes: 39 additions & 26 deletions schema/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ var _escData = map[string]*_escFile{
"/config-schema.json": {
local: "config-schema.json",
size: 707,
modtime: 1463700693,
modtime: 1464139547,
compressed: `
H4sIAAAJbogA/5SRPW7DMAyF5/oUhpOxjjp0ytoDdOgJVJmKGcCiQDJDUPju1U/c2kvhLobx+L73JOqr
adtuAHGMUZFCd2679wjhjYJaDMBt+vN4aT8iOPTobHE9Z+woboTJZmRUjWdjrkKhr+qJ+GIGtl77l1dT
Expand All @@ -213,10 +213,23 @@ T4aE9IoTdGU2V0tnbzoS/xG1dbMbUdPhbgx7GZK9zscuVu4jgy+HBy99HZ/yKxxMUjBgfi1ZdrjJYiL1
`,
},

"/content-descriptor.json": {
local: "content-descriptor.json",
size: 616,
modtime: 1464914956,
compressed: `
H4sIAAAJbogA/4yRMVPDMAyF9/wKXdqR1gxMXWFngI1jcG0lVe9iG1kMhet/x4oTSGGgW/L8vvck+7MB
aD1mx5SEYmh30D4mDPcxiKWADPqFQeBhMkWGp4SOOnJ2JG40Yp3dAQer+EEk7Yw55hg2Vd1G7o1n28nm
9s5UbVU58jOSCxNLs5ub84hVt/Hf7ZWTU0Il4/6ITqqWuPAshLmc6GJFG9CTfa7mKv3dVw4Io09DIXag
AmOHXKZBD4uOEV+XM+U8dnlDg+1xq8uuyj8F0tRsfnpH6lzhNtPHf5OoBSjA/iSYr5hmvgkqz9QjX/Z5
6jHLsvGa4SeqJjVTWsv49k6M+mAvvy93ud5ldfl5bc7NVwAAAP//Zc2MR2gCAAA=
`,
},

"/defs-config.json": {
local: "defs-config.json",
size: 1755,
modtime: 1463700704,
modtime: 1464139547,
compressed: `
H4sIAAAJbogA/7xUzc7TMBA8N09hBY6BXhAHri1HVKQIOFZusm63xF5rvQEi1HfHSauS/qRKKV8PVeOx
Z2bXY/t3olRaQigYvSC59INK52DQYTsKymsWLOpKsxJSCw9uRk40OmAVvwyuVe6hQIOF7vjZXvCoEAVb
Expand All @@ -230,27 +243,27 @@ W1SwXppll8oQfUVUgXaDqSTtb5f8CQAA//8Cok052wYAAA==

"/defs-image.json": {
local: "defs-image.json",
size: 3100,
modtime: 1462965360,
size: 2528,
modtime: 1464914958,
compressed: `
H4sIAAAJbogA/+xWy27bMBC86ysIJUAOfqjXGkGAoEGBnlIgPdVQgY20kphKpLqkgzqB/r3U+x3Xidte
erK55A5nhmPSzxZjto/KI55qLoW9YfYNBlzwfKRYCqS5t4uBmJbsNkXxQQoNXCCxTwmEyO5S9HjAPSja
lyVeA2Dw8i1MMUGfw5d9ik3JFLmfbxhpnaqN40gD79Xwai0pdJQXYQIOz7dyWohlDaBLQFtp4iJs6ylo
jVTI+baF1ZO7cLbvVu/Nt+vV1/XCXZzbxdKs7LB9HqLSXWoDU3SEzKN9qmVIkEbcY4aZ913tElb2Mhmw
fJG8f0BPLxkXxbAiwi4uI1DR1eYywp/gG8sSiKvOq4vj9Rgt7mJjvgXXq4/FYCiooi/p9X53MEYES5lt
nfDHjhPm+Nuq1jv0ZVtU/Kk3rryvCm6rmQxBEz9UHQkzSZo7smJtzrk+HsIAychGnw0kFBDnZj7vPetk
uJO7Zmk21HOYSr4sT8X9XqP6TTq121xoDJGm9x9ld15J32oDY3U/6+wkIHhg1t2cIEMTWH8hS51KGoMO
JCX/8/Uv8jV1EAOg4/LUoEzqmNI4maZiBsiLuDYNO8Jej5mTyu4U3B7iTHDGmMPZV6t1XqA6fjV609lY
2OloGbA3klk/mh3KFJ+OVAP6VnIBQu74aS1rUWfpARHsx9MmAckUlwPC2nt+WugjEAcx/IUf7ddLZv0x
YSMo8P3iMoL4c/dnGkCs0JrzJDvwIoIQUkP/H+3REeiCNI+QFHgb9K6myVvWXLJq/aCkOHN6Lwekd4Uv
dwN3Or48T12UYhfH478BrlWPMiuzfgUAAP//VjUNyBwMAAA=
H4sIAAAJbogA/7RWy27bMBC8+ysIJUAOfqjXGkGAoEGBnlIgPTVQgY20kphKpLqkgzqB/r2k3k+nrt0b
ueQOZ4Zjym8LxpwAlU8801wKZ8ucOwy54HamWAakub9LgJiW7D5D8UkKDVwgsS8pRMgeMvR5yH0o2lcl
XgNg8OwRpphiwOHbPsOmZIo8sAfGWmdq67rSwPs1vNpIilzlx5iCy+1RbguxqgF0CegoTVxEbT0DrZEK
OT8eYf3qLd3HD+uPZnS7/r5ZestLp9ialx1OwCNUukttYIqOkfm0z7SMCLKY+8ww83+qXcrKXiZDZjfJ
p2f09YpxUUwrIuzqOgYV32yvY/wNgbEshaTqvLk6Xo/R4i23ZhTerj8Xk4GgFAQPDfhdJUPSCb6PsUaE
S9ltnfDXjhPacx6rWi8Eq7ao+GtvXt1Fp5IloENJqVOVvNYXMuRNRFF15M2kbe5ai71WR32FhCGSsQQD
NpBVQFyaddt70cl5J5vN1nyo8X0qdptNztNeo/pLOvUNcKExQpo+f5TveSXV1kmY5iIGQMflqUGZ1DGl
cTJNxQqQH3NtGnaEvR6zJpXTKXg9xJngjDGHq/+s1j1AdfzL7y3nY2Hno2XATiSzeTEnlCk+H6kG9FRy
IYJ1/LyWtaiz9IAI9uNlk4B0iss7woy0g0JfgDiI4S/8aL8OmfXfhI2gIAiKxwiSr92faQiJwsWcJ+24
HuW9LyIIITX0/5UcHYEuSPMRkgLvw97TNPnKmkdWbZ6VFBdu78sB2UPhy8PAnY4vb1MPpdgliTMS7S3q
Wb7IF38CAAD//wKthPngCQAA
`,
},

"/defs.json": {
local: "defs.json",
size: 3193,
modtime: 1463700693,
modtime: 1464139547,
compressed: `
H4sIAAAJbogA/7RWTXPaMBC98ys8tEfa2PIX9NYp/cghAzOZnjo9uGYBtSCpstxpmuG/VzLGWPZiMKWH
JPau9r23T6tYzwPHGS4gSyUVinI2fOMMp7CkjJq3zMkzWDhqLXm+WvNc6UdwZgLYO85UQhlI51FASpc0
Expand All @@ -268,23 +281,23 @@ MrVJbn8cB+ZnN/gbAAD//0JyEpx5DAAA

"/image-manifest-schema.json": {
local: "image-manifest-schema.json",
size: 1064,
modtime: 1462965360,
size: 1032,
modtime: 1464914959,
compressed: `
H4sIAAAJbogA/6RTvVLjMBDu/RQ7TspzdMVVaa+64oaCDA1DIeyVvZlYMlrBTCaTd0c/UZAJBSSlV/v9
Sj5UAHWH3FqaHBldr6G+m1D/NdpJ0mjh3yh7hP9Sk0J2cD9hS4paGbd/BfiS2wFHGaCDc9NaiC0b3aTp
ythedFYq1/z+I9JskXDUZQh7jPGqbVblCEvbgoIDMZ4cJKzbTxjQ5nmL7Wk2Wc9hHSH7kxDMzxLFg2dM
4dL4MvNmIAZFuOuAU0JkcANCFIcsDokP3hIhSAapgbTDHm10EcmvSybmZs9sOWuWifNjOq5H7Ehu0sbh
Rv0PrrP20qIKXB0qbuL6KlzuQvgBaQr1cYGbWfOaivrS17fY8s2YT0l3cu/tl3S5GGmt3BftOxzLvWuF
vfTMgNTauPju+faymx35xkvKn3VeIqvsNTqtLb68ksVg6/Grv+Di5czva163/3iqjtV7AAAA///++ypf
KAQAAA==
H4sIAAAJbogA/6RSPU/zMBDe8ytOacc39TswdWViQAxULIjBJOfkqsYOPoNUVf3v+KMujsoAdMyTez7u
8R0qgLpDbi1Njoyu11A/TKhvjXaSNFq4G2WPcC81KWQHjxO2pKiVcfpfoC+5HXCUgTo4N62F2LLRTUJX
xvais1K55v+NSNgi8ajLFPYc413b7MqRlqYFhQRiPCVIXLefMLDN6xbbEzZZr2EdIfs/YTGPJYknr5iW
S/DlzpuBGBThrgNOGyKDGxCiOWRzSHrwkQRBMkgNpB32aGOKKP63zcQ87Fkt75ptIn5Mv+sRO5KbNHG4
0v9L6+y9tKiCVoeKmzi+Co+7EB4gTaE+LnizaN5TUV/mymohDWrX5EcwNqrO6Tu593FLei5CWiv3RdsO
x3Lup0beamYotTYu3jVfX2azI99oKfm7TktmlbPGpLXFt3eyGGI9f3flF5cxf495vf7jpTpWnwEAAP//
X3p8DwgEAAA=
`,
},

"/manifest-list-schema.json": {
local: "manifest-list-schema.json",
size: 1010,
modtime: 1462965360,
modtime: 1464139547,
compressed: `
H4sIAAAJbogA/6ySMU/7MBDF93yKU9rxn/o/MHWFBQnEQMWCGExyaa5q7OAzSFXV747tS0qiMIDoUqkv
fu9+7+xjBpBXyKWjzpM1+Rryhw7NtTVek0EHt63eItxrQzWyhzsKP48dllRTqZPlX8xYctlgq6O/8b5b
Expand Down
4 changes: 2 additions & 2 deletions schema/image-manifest-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
"$ref": "defs-image.json#/definitions/mediaType"
},
"config": {
"$ref": "defs-image.json#/definitions/descriptor"
"$ref": "content-descriptor.json"
},
"layers": {
"type": "array",
"items": {
"$ref": "defs-image.json#/definitions/descriptor"
"$ref": "content-descriptor.json"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reckon this is fine, but seems just as well to make it an object within a defs*.json file, rather than adding a new file just for a single definition.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, but it can have it's own schema file to be validated against ... hrm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we'll have to shuffle the organization a bit, but, yes, this allows individual validation in the current test setup.

}
},
"annotations": {
Expand Down
2 changes: 2 additions & 0 deletions schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import "net/http"

// Media types for the OCI image formats
const (
MediaTypeDescriptor Validator = `application/vnd.oci.descriptor.v1+json`
MediaTypeManifest Validator = `application/vnd.oci.image.manifest.v1+json`
MediaTypeManifestList Validator = `application/vnd.oci.image.manifest.list.v1+json`
MediaTypeImageSerialization unimplemented = `application/vnd.oci.image.serialization.rootfs.tar.gzip`
Expand All @@ -32,6 +33,7 @@ var (

// specs maps OCI schema media types to schema files.
specs = map[Validator]string{
MediaTypeDescriptor: "content-descriptor.json",
MediaTypeManifest: "image-manifest-schema.json",
MediaTypeManifestList: "manifest-list-schema.json",
MediaTypeImageSerializationConfig: "config-schema.json",
Expand Down
4 changes: 4 additions & 0 deletions schema/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ var (
errFormatInvalid = errors.New("format: invalid")
)

func TestValidateDescriptor(t *testing.T) {
validate(t, "../descriptor.md")
}

func TestValidateManifest(t *testing.T) {
validate(t, "../manifest.md")
}
Expand Down