Skip to content

Latest commit

 

History

History
636 lines (500 loc) · 28.3 KB

DESIGN.md

File metadata and controls

636 lines (500 loc) · 28.3 KB

OCI Parcel Extension

This document is an extension to the Open Container Initiative (OCI) image specification, adding a discovery and read-only distribution interface. The intention of this extension is to be as protocol-agnostic as possible with regards to the distribution protocol (with the possibility for extensions to the discovery protocol to make it also protocol-agnostic).

The current state of container image distribution has several issues, which this extension attempts to improve:

  • The docker:// protocol and schema are not truly state-less HTTP, and therefore cannot be implemented by a "dumb" CDN. By necessity a stateful application must be run by a distributor, which is not always reasonable or possible. It also makes caching harder to implement for something like Varnish.

  • The docker:// protocol is the only "official" way of distributing such images, which makes other methods of distribution (saving an image and then distributing it via FTP, BitTorrent, etc) out-of-band and not supported. While this extension does not require that all such methods be support, it elevates their usefulness by making them much more supportable.

  • Image "naming" and distribution are linked, tying the orthogonal issues of identity and source-of-files. This further complicates the jobs of CDNs, requiring them to provide DNS round-robin style distribution rather than GNU/Linux distribution "mirroring".

The usage of the terms MUST, MUST NOT, MAY, SHOULD, and SHOULD NOT in this document is described by RFC 2119. Lower-case usage of these terms SHOULD NOT be taken to be the same as upper-case usage.

This document makes usage of the JSON interchange format, and when specifying the fields of JSON objects a similar style to the OCI image and runtime specifications is used.

The key premise of this extension is to allow domains to specify a policy for how OCI images are hosted (using this extension). A domain can either enumerate their own hosting scheme (based on distribution objects), or can delegate to another distributor domain. This allows this extension to be overlayed on existing distribution systems and allow for future migration transparently.

Implementation

The following sections describe in detail the steps required for an implementation of this specification to go from image discovery (stage0), through parsing of template descriptors and distribution objects (stage1), to arrive at OCI image blob and index fetching (stage2).

Template Descriptor

A very important property of parcel is that it should be possible to statically describe any nested structure of redirects, as well as opening the door to future extensions. This data structure is heavily inspired by the OCI image-spec descriptor objects.

The following object MUST be interpreted as a JSON object. When referencing this object, the MIME type is defined to be application/vnd.parcel.template-descriptor.v0+json.

The following fields are defined by this specification, and MUST at least be implemented. Additional fields MAY be supported by implementations, however if an additional field is not supported by an implementation it MUST be ignored by the implementation.

  • mediaType (string, REQUIRED)

    Th media type of the referenced content. Values MUST comply with RFC 6838, including the naming requirements in § 4.2.

    Note that this document defines an opaque MIME type.

  • templates (array of strings, REQUIRED)

    The list of URI templates from which this object MUST be downloaded. Values MUST comply with RFC 6570 and MAY contain variables defined by this specification. If a variable is not available at the time of resolving a template URI, the implementation MUST emit a warning and no longer consider the faulty template (an implementation MAY attempt to use an alternative template).

  • annotations (object, OPTIONAL)

    The semantics of this object are identical to the annotation rules for the OCI image-spec.

If a template descriptor references another template descriptor, an implementation MUST retrieve the referenced template descriptor and MUST resolve it as though it were the original descriptor. Implementations SHOULD place a limit on the number of references to be resolved, to avoid denial-of-service and amplification attacks.

An example application/vnd.parcel.template-descriptor.v0+json object follows.

{
	"mediaType": "application/vnd.oci.image.manifest.v1+json",
	"templates": [
		"http://download.opensuse.org/repositories/Virtualization:/containers/images/{parcel.version}/{parcel.discovery.nameDigest}/{parcel.fetch.blob.digest}",
		"https://mirror.cyphar.com/opensuse/blobs/{parcel.fetch.blob.digestAlgorithm}:{parcel.fetch.blob.digest}",
		"ftp://legacy.ftp.suse.com/REPO/{parcel.fetch.blob.digest}"
	],
	"annotations": {
		"com.cyphar.createdDate": "1997-03-25T13:40:00+01:00",
		"org.opensuse.maintainer": "Aleksa Sarai <cyphar@opensuse.org>"
	}
}

Opaque MIME

Template descriptors allow for arbitrary blob URLs to be encoded in a single descriptor. In certain cases, this may mean that the MIME type of a particular URI template is not well-defined. This section describes a special-purpose MIME type that is used in this case.

application/vnd.parcel.opaque.v0 is an RFC 6838 compliant MIME type that represents a blob whose MIME type MUST be derived from alternative sources. If an implementation cannot determine the MIME type through alternative means before retrieving the content, it MUST emit an error.

Implementations SHOULD NOT use opaque MIME types except in cases where required by this specification and MAY emit an error if one is encountered outside of the scope of this specification.

Image Discovery

In order for a user to be able to describe what image they want to download, a discovery system is required. Note that while this discovery system MUST be implemented, implementations MAY choose to allow users to bypass the discovery URLs and directly specify a distribution object.

The purpose of this section is to describe how to resolve a "discovery URI" into a distribution object (possibly after being given several layers of template descriptors which have been dereferenced). Implementations of this section are referred to as "explorers".

A "discovery URI" is defined by the following syntax, where authority and path-rootless are defined by RFC 3986 § 3. In the following section, <authority> and <path> refer to the authority section and the "rest" of the URI.

distribution-uri   = authority "/" path-rootless

With a fully resolved <authority> value, an explorer MUST then attempt to find a suitable top-level object that can be traversed to find the corresponding distribution object.

An explorer MUST attempt to fetch the data present at https://<authority>/.well-known/x-parcel (using HTTP over TLS). The contents of this file is a series of newline-separated strings that specify what versions of the parcel specification the distributor supports. If no data is present, or the URL cannot be accessed, then the explorer SHOULD emit a warning and continue fetching using the latest version supported by the explorer. If the data is incorrectly formatted, or the explorer does not support any of the versions specified by the distributor, the explorer MUST emit an error and halt fetching. If multiple versions are supported by both the explorer and distributor, the explorer SHOULD use the highest version supported by both parties (using the [SemVer rules for version comparison][semver-cmp]). An example of this file follows. Explorers SHOULD take care to ensure that the version values are valid (to avoid path-traversal attacks as well as general confusion).

v2.0.0
v1.4.2
v1.0.0-alpha2
v0.4.12-rc2

Once a version has been chosen, the explorer must then attempt to access and fetch https://<authority>/.well-known/x-parcel.<version> (using HTTP over TLS), where <version> is the agreed-upon version. If an error occurs when trying to access this URL, an explorer MAY attempt to resolve additional URLs (such as alternative versions, or out-of-spec URLs). The contents of this URL MUST be parsed as a template descriptor.

Distribution URL

The purpose of this section is to describe how to resolve a "distribution URI-reference" to index and blob retrieval URL templates which can be used to download the blobs of an image. The process of discovering a distribution URI-reference for a given "user friendly" discovery URI is described in the image discovery section. An implementation of this section is referred to as a "consumer".

The syntax of a "distribution URI-reference" (and part of the semantic meaning) is described by URI-reference in RFC 3986 § 4.1. If a consumer encounters an invalid "distribution URI-reference", it MUST emit an error.

The consumer MUST resolve the distribution URI-reference as a "URI reference" as described in RFC 3986 § 5 to provide a fully qualified "distribution URL". If necessary to resolve the distribution URI-reference, the "base URI" used MUST be http://<authority>/, with <authority> defined through the same resolution process as in the discovery stage.

After resolving the URI-reference, the distribution URL MUST be resolved as described in known schemas and its contents parsed as a distribution object. If an error occurs during resolution or parsing, the consumer MUST emit an error.

Plain Distribution Object

In order to allow for a "dumb" CDN to be able to distribute all of the pieces of an OCI image, it is necessary to have a way of specifying a set of templates that a client can evaluate to produce a set of URLs where the index and blobs for an image can be retreived from.

The following object MUST be interpreted as a JSON object. When referencing this object, the MIME type is defined to be application/vnd.parcel.plain-distribution.v0+json.

The following fields are defined by this specification, and MUST at least be implemented. Additional fields MAY be supported by implementations, however if an additional field is not supported by an implementation it MUST be ignored by the implementation.

  • indexURIs (array of object (template descriptor), REQUIRED)

    The list of template descriptors which MUST be used by fetchers to get the contents of the OCI image's image index. Fetchest SHOULD use the contents of the image index in order to ascertain (by walking OCI's Descriptor paths) the minimal set of blobs that must be downloaded to fulfil the user's request.

    A fetcher MUST support the following MIME types for this entry. Fetchers MAY support additional MIME types, but MUST emit an error if an unsupported MIME type is encountered.

    A fetcher SHOULD NOT re-fetch the image index more than once in a single image download. However, the fetcher MAY fetch the image index using different template entries in the indexURIs array in subsequent fetches.

  • blobURIs (array of object (template descriptor), REQUIRED)

    The list of template descriptors which MUST be used by fetchers to get the contents of any content-addressable blob (in the context of the distribution URL).

    A fetcher MUST support the following MIME types for this entry. Fetchers MAY support additional MIME types, but MUST emit an error if an unsupported MIME type is encountered.

    In addition, fetchers SHOULD support the OCI image-spec's MIME types. If a particular blob's MIME type is explicitly listed in blobURIs (as opposed to just using opaque MIME types) then a fetcher MAY use any of the available blobURIs entries. However, a fetcher MUST NOT attempt to use a blobURIs entry to fetch a blob that has a conflicting MIME type to the template descriptor.

    A fetcher SHOULD NOT re-fetch a given blob more than once in a single image download. Fetchers MAY fetch blobs using different template entries in the blobURIs array.

  • annotations (object, OPTIONAL)

    The semantics of this object are identical to the annotation rules for the OCI image-spec.

NOTE: Servers MAY wish to use the array of bloburis to allow for specifying "official" mirrors of blobs (where the mirrors may wish to use further load-balancers). As such, fetchers MAY wish to take this intention into account and round-robin (as well as parallelise) the fetching of blobs.

An example application/vnd.parcel.plain-distribution.v0+json object follows.

{
	"indexURIs": [
		{
			"mediaType": "application/vnd.oci.image.index.v1+json",
			"templates": [
				"https://mirror.cyphar.com/opensuse/index.json",
				"ftp://legacy.ftp.suse.com/REPO.json"
			],
			"annotations": {
				"org.opensuse.maintainer": "Jane Doe <jane@doe.com>"
			}
		},
		{
			"mediaType": "application/vnd.parcel.template-descriptor.v0+json",
			"templates": [
				"https://mirror2.cyphar.com/opensuse_desc.json",
			]
		}
	],
	"blobURIs": [
		{
			"mediaType": "application/vnd.oci.image.manifest.v1+json",
			"templates": [
				"https://manifests.cyphar.com/opensuse/{parcel.discovery.nameDigest}/manifests/{parcel.fetch.blob.digestAlgorithm}/{parcel.fetch.blob.digest}"
			]
		},
		{
			"mediaType": "application/vnd.parcel.opaque.v0",
			"templates": [
				"https://blobs.cyphar.com/{parcel.discovery.nameDigest}/blobs/{parcel.fetch.blob.digestAlgorithm}/{parcel.fetch.blob.digest}"
			],
			"annotations": {
				"org.foo.bar": "baz",
			}
		}
	],
	"annotations": {
		"com.cyphar.createdDate": "2020-05-23T19:42:42+11:00"
	}
}

Image Blob Retrieval

The final stage of fetching an OCI image is actually resolving, fetching and parsing the OCI image index and various associated blobs.

The purpose of this section is to describe how to use the indexuris and bloburis arrays sourced during the distribution stage of parcel fetching. An implementation of this section is referred to as a "fetcher".

After evaluation of the URI-reference templates as described by in the distribution object section, the syntax of the index and blob URI-references (and part of their semantic meaning) is described by URI-reference in RFC 3986 § 4.1.

The fetcher MUST resolve both index and blob URI-references as "URI reference", as described in RFC 3986 § 5 to produce fully qualified index and blob URLs. If necessary to resolve the distribution URI-reference, the "base URI" used MUST be the distribution URL used to download the distribution object.

If an index or blob URI-reference is invalid, the fetcher MUST act as though the invalid URI-reference was not present in the original set of URI-references (though it SHOULD emit a warning). If there are no valid URI-references in the set of blob or index URI-references, the fetcher MUST emit an error.

After resolving the URI-references, the resultant URLs MUST be resolved as described in known schemas and their contents SHOULD be parsed as appropriate for their OCI image mediaTypes. If an unknown mediaType is encountered, fetchers SHOULD download the blob without parsing it (though they SHOULD emit a warning that the downloaded image may be incomplete).

NOTE: While the algorithm for deciding what blobs are necessary to download is not specified by this document, fetchers SHOULD attempt a recursive OCI Descriptor walk to decide the set of blobs that are necessary to fulfil a top-level index entry requirement (which is retrieved from the indexuris and parsed as an OCI image index).

Prior Art

This extension was heavily influenced by the AppC image discovery specification, as well as personal concerns of the author with regards to the current (centralised and protocol-centric) state of container image distribution.

In addition, one of the very large concerns of this extension was to ensure that pre-existing distribution systems (such as the Open Build Service) will be able to seamlessly publish these sorts of images (and that their pre-existing CDN integrations would also operate smoothly), without requiring RPM wrapping around all of the blobs.

The eventual intention is that projects like openSUSE's containment-rpm will be able to produce parcel repositories (with the discovery being published separately on the main opensuse.org website), taking advantage of the existing OBS infrastructure and CDN setup.

Version

This document is versioned in accordance with Semantic Versioning v2.0.0. The current version of this document is 0.0.0, and is currently considered a DRAFT.

Copyright

This document is licensed under the Apache 2.0 license.

Copyright (C) 2017 SUSE LLC.

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.

Appendix

This section and sub-sections define supplementary definitions of syntax and other semantics. They SHOULD NOT be used outside of the context of this specification.

URI Template Variables

The following variables are defined by this specification. If a variable is listed as REQUIRED then an implementation MUST allow substitution of that variable, and OPTIONAL variables mean that an implementation SHOULD allow substitution of that variable.

These variables are namespaced -- implementations MAY extend the following list of variables (and SHOULD also namespace their variables), but all variables in the parcel namespace (those prefixed with parcel.) MUST NOT be used except as specified in this document (they are reserved for future extensions).

The following variables are defined from the discovery stage onwards. If an implementation did not consume a discovery object, it MUST use the values defined as the default discovery object in the discovery stage.

  • parcel.discovery.authority (string, REQUIRED)

    The final value of <authority> computed by the explorer, which MAY be different from the <authority> specified by the user.

  • parcel.discovery.userAuthority (string, REQUIRED)

    The value of <authority> as provided by the user, which MAY be different from parcel.authority.

  • parcel.discovery.name (string, REQUIRED)

    The value of <name> as specified by the user.

  • parcel.discovery.nameDigest (string, REQUIRED)

    The lowercase hexadecimal representation of the digest of the <name> specified by the user, using the digest specified by the discovery object. If the explorer does not support the digest specified, it MUST emit an error.

  • parcel.discovery.digestAlgorithm (string, REQUIRED)

    The name of the digest algorithm specified by the discovery object.

The following variables are defined from the blob retrieval stage stage onwards. An implementation MUST define these variables when fetching a bloburi.

  • parcel.fetch.blob.algorithm (string, REQUIRED)

    The name of the digest algorithm used for producing the digest of an OCI image blob, as specified by the OCI descriptor that resulted in the blob being fetched. The syntax and semantic meaning of this value is described in the OCI image specification as algorithm.

  • parcel.fetch.blob.digest (string, REQUIRED)

    The lowercase hexadecimal representation of the blob digest. The syntax and semantic meaning of this value is described in the OCI image specification as hex.

Known Schemes

While implementations of this specification MAY implement additional scheme support, any implementation MUST obey this section (if instructed to by the main document).

If the scheme or protocol in the given URI is not supported, the implementation MUST emit an error. Consumers MUST implement at least the following schemes and protocols:

In addition, the following protocols SHOULD be implemented by implementations. If an implementation implements the following schemes, the semantics MUST match those described below.

  • ftp refers to the File Transfer Protocol. Consumers SHOULD attempt to log in with anonymous credentials before prompting a user for credentials.

  • magnet refers to a BitTorrent Magnet URI, with an optional RFC 3986 § 3.5 fragment. If the URI indicates a BitTorrent info-hash, fragment indicates the filename within the info dictionary that the implementation MUST use as the contents of the magnet URI. If the URI does not indicate an info-hash, fragment MUST be ignored by implementations.

  • ipfs and ipns are reserved for use by Interplanetary File System URIs. Consumers MUST emit an error if they encounter these schemes (this may change in the future).