Rust implementation of OCI Distribution Spec with granular access control
at main 859 lines 47 kB view raw view rendered
1# Open Container Initiative Distribution Specification 2 3## Table of Contents 4 5- [Overview](#overview) 6 - [Introduction](#introduction) 7 - [Historical Context](#historical-context) 8 - [Definitions](#definitions) 9- [Notational Conventions](#notational-conventions) 10- [Use Cases](#use-cases) 11- [Conformance](#conformance) 12 - [Official Certification](#official-certification) 13 - [Requirements](#requirements) 14 - [Workflow Categories](#workflow-categories) 15 1. [Pull](#pull) 16 2. [Push](#push) 17 3. [Content Discovery](#content-discovery) 18 4. [Content Management](#content-management) 19- [Backwards Compatibility](#backwards-compatibility) 20 - [Unavailable Referrers API](#unavailable-referrers-api) 21- [Upgrade Procedures](#upgrade-procedures) 22 - [Enabling the Referrers API](#enabling-the-referrers-api) 23- [API](#api) 24 - [Endpoints](#endpoints) 25 - [Error Codes](#error-codes) 26 - [Warnings](#warnings) 27- [Appendix](#appendix) 28 29 30## Overview 31 32### Introduction 33 34The **Open Container Initiative Distribution Specification** (a.k.a. "OCI Distribution Spec") defines an API protocol to facilitate and standardize the distribution of content. 35 36The specification is designed to be agnostic of content types. 37OCI Image types are currently the most prominent, which are defined in the [Open Container Initiative Image Format Specification](https://github.com/opencontainers/image-spec) (a.k.a. "OCI Image Spec"). 38 39### Historical Context 40 41The spec is based on the specification for the Docker Registry HTTP API V2 protocol <sup>[apdx-1](#appendix)</sup>. 42 43For relevant details and a history leading up to this specification, please see the following issues: 44 45- [moby/moby#8093](https://github.com/moby/moby/issues/8093) 46- [moby/moby#9015](https://github.com/moby/moby/issues/9015) 47- [docker/docker-registry#612](https://github.com/docker/docker-registry/issues/612) 48 49#### Legacy Docker support HTTP headers 50 51Because of the origins of this specification, the client MAY encounter Docker-specific headers, such as `Docker-Content-Digest`, or `Docker-Distribution-API-Version`. 52These headers are OPTIONAL and clients SHOULD NOT depend on them. 53 54#### Legacy Docker support error codes 55 56The client MAY encounter error codes targeting Docker schema1 manifests, such as `TAG_INVALID`, or `MANIFEST_UNVERIFIED`. 57These error codes are OPTIONAL and clients SHOULD NOT depend on them. 58 59### Definitions 60 61Several terms are used frequently in this document and warrant basic definitions: 62 63- **Registry**: a service that handles the required APIs defined in this specification 64- **Repository**: a scope for API calls on a registry for a collection of content (including manifests, blobs, and tags). 65- **Client**: a tool that communicates with Registries 66- **Push**: the act of uploading blobs and manifests to a registry 67- **Pull**: the act of downloading blobs and manifests from a registry 68- **Blob**: the binary form of content that is stored by a registry, addressable by a digest 69- **Manifest**: a JSON document uploaded via the manifests endpoint. A manifest may reference other manifests and blobs in a repository via descriptors. Examples of manifests are defined under the OCI Image Spec <sup>[apdx-2](#appendix)</sup>, such as the image manifest and image index (and legacy manifests).</sup> 70- **Image Index**: a manifest containing a list of manifests, defined under the OCI Image Spec <sup>[apdx-6](#appendix)</sup>. 71- **Image Manifest**: a manifest containing a config descriptor and an indexed list of layers, commonly used for container images, defined under the OCI Image Spec <sup>[apdx-2](#appendix)</sup>. 72- **Config**: a blob referenced in the image manifest which contains metadata. Config is defined under the OCI Image Spec <sup>[apdx-4](#appendix)</sup>. 73- **Object**: one conceptual piece of content stored as blobs with an accompanying manifest. (This was previously described as an "artifact") 74- **Descriptor**: a reference that describes the type, metadata and content address of referenced content. Descriptors are defined under the OCI Image Spec <sup>[apdx-5](#appendix)</sup>. 75- **Digest**: a unique identifier created from a cryptographic hash of a Blob's content. Digests are defined under the OCI Image Spec <sup>[apdx-3](#appendix)</sup> 76- **Tag**: a custom, human-readable pointer to a manifest. A manifest digest may have zero, one, or many tags referencing it. 77- **Subject**: an association from one manifest to another, typically used to attach an artifact to an image. 78- **Referrers List**: a list of manifests with a subject relationship to a specified digest. The referrers list is generated with a [query to a registry](#listing-referrers). 79 80## Notational Conventions 81 82The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119) (Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997). 83 84## Use Cases 85 86### Content Verification 87 88A container engine would like to run verified image named "library/ubuntu", with the tag "latest". 89The engine contacts the registry, requesting the manifest for "library/ubuntu:latest". 90An untrusted registry returns a manifest. 91After each layer is downloaded, the engine verifies the digest of the layer, ensuring that the content matches that specified by the manifest. 92 93### Resumable Push 94 95Company X's build servers lose connectivity to a distribution endpoint before completing a blob transfer. 96After connectivity returns, the build server attempts to re-upload the blob. 97The registry notifies the build server that the upload has already been partially attempted. 98The build server responds by only sending the remaining data to complete the blob transfer. 99 100### Resumable Pull 101 102Company X is having more connectivity problems but this time in their deployment datacenter. 103When downloading a blob, the connection is interrupted before completion. 104The client keeps the partial data and uses http `Range` requests to avoid downloading repeated data. 105 106### Layer Upload De-duplication 107 108Company Y's build system creates two identical layers from build processes A and B. 109Build process A completes uploading the layer before B. 110When process B attempts to upload the layer, the registry indicates that its not necessary because the layer is already known. 111 112If process A and B upload the same layer at the same time, both operations will proceed and the first to complete will be stored in the registry. 113Even in the case where both uploads are accepted, the registry may securely only store one copy of the layer since the computed digests match. 114 115## Conformance 116 117For more information on testing for conformance, please see the [conformance README](./conformance/README.md) 118 119### Official Certification 120 121Registry providers can self-certify by submitting conformance results to [opencontainers/oci-conformance](https://github.com/opencontainers/oci-conformance). 122 123### Requirements 124 125Registry conformance applies to the following workflow categories: 126 1271. **Pull** - Clients are able to pull from the registry 1282. **Push** - Clients are able to push to the registry 1293. **Content Discovery** - Clients are able to list or otherwise query the content stored in the registry 1304. **Content Management** - Clients are able to control the full life-cycle of the content stored in the registry 131 132All registries conforming to this specification MUST support, at a minimum, all APIs in the **Pull** category. 133 134Registries SHOULD also support the **Push**, **Content Discovery**, and **Content Management** categories. 135A registry claiming conformance with one of these specification categories MUST implement all APIs in the claimed category. 136 137In order to test a registry's conformance against these workflow categories, please use the [conformance testing tool](./conformance/). 138 139### Workflow Categories 140 141#### Pull 142 143The process of pulling an object centers around retrieving two components: the manifest and one or more blobs. 144 145Typically, the first step in pulling an object is to retrieve the manifest. However, you MAY retrieve content from the registry in any order. 146 147##### Pulling manifests 148 149To pull a manifest, perform a `GET` request to a URL in the following form: 150`/v2/<name>/manifests/<reference>` <sup>[end-3](#endpoints)</sup> 151 152`<name>` refers to the namespace of the repository. 153`<reference>` MUST be either (a) the digest of the manifest or (b) a tag. 154The `<reference>` MUST NOT be in any other format. 155Throughout this document, `<name>` MUST match the following regular expression: 156 157`[a-z0-9]+((\.|_|__|-+)[a-z0-9]+)*(\/[a-z0-9]+((\.|_|__|-+)[a-z0-9]+)*)*` 158 159_Implementers note:_ 160Many clients impose a limit of 255 characters on the length of the concatenation of the registry hostname (and optional port), `/`, and `<name>` value. 161If the registry name is `registry.example.org:5000`, those clients would be limited to a `<name>` of 229 characters (255 minus 25 for the registry hostname and port and minus 1 for a `/` separator). 162For compatibility with those clients, registries should avoid values of `<name>` that would cause this limit to be exceeded. 163 164Throughout this document, `<reference>` as a tag MUST be at most 128 characters in length and MUST match the following regular expression: 165 166`[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}` 167 168The client SHOULD include an `Accept` header indicating which manifest content types it supports. 169In a successful response, the `Content-Type` header will indicate the type of the returned manifest. 170The registry SHOULD NOT include parameters on the `Content-Type` header. 171The client SHOULD ignore parameters on the `Content-Type` header. 172The `Content-Type` header SHOULD match what the client [pushed as the manifest's `Content-Type`](#pushing-manifests). 173If the manifest has a `mediaType` field, clients SHOULD reject unless the `mediaType` field's value matches the type specified by the `Content-Type` header. 174For more information on the use of `Accept` headers and content negotiation, please see [Content Negotiation](./content-negotiation.md) and [RFC7231](https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1). 175 176A GET request to an existing manifest URL MUST provide the expected manifest, with a response code that MUST be `200 OK`. 177A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`. 178 179The `Docker-Content-Digest` header, if present on the response, returns the canonical digest of the uploaded blob which MAY differ from the provided digest. 180If the digest does differ, it MAY be the case that the hashing algorithms used do not match. 181See [Content Digests](https://github.com/opencontainers/image-spec/blob/v1.0.1/descriptor.md#digests) <sup>[apdx-3](#appendix)</sup> for information on how to detect the hashing algorithm in use. 182Most clients MAY ignore the value, but if it is used, the client MUST verify the value matches the returned manifest. 183If the `<reference>` part of a manifest request is a digest, clients SHOULD verify the returned manifest matches this digest. 184 185If the manifest is not found in the repository, the response code MUST be `404 Not Found`. 186 187##### Pulling blobs 188 189To pull a blob, perform a `GET` request to a URL in the following form: 190`/v2/<name>/blobs/<digest>` <sup>[end-2](#endpoints)</sup> 191 192`<name>` is the namespace of the repository, and `<digest>` is the blob's digest. 193 194A GET request to an existing blob URL MUST provide the expected blob, with a response code that MUST be `200 OK`. 195A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`. 196If present, the value of this header MUST be a digest matching that of the response body. 197Most clients MAY ignore the value, but if it is used, the client MUST verify the value matches the returned response body. 198Clients SHOULD verify that the response body matches the requested digest. 199 200If the blob is not found in the repository, the response code MUST be `404 Not Found`. 201 202A registry SHOULD support the `Range` request header in accordance with [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-range-requests). 203 204##### Checking if content exists in the registry 205 206In order to verify that a repository contains a given manifest or blob, make a `HEAD` request to a URL in the following form: 207 208`/v2/<name>/manifests/<reference>` <sup>[end-3](#endpoints)</sup> (for manifests), or 209 210`/v2/<name>/blobs/<digest>` <sup>[end-2](#endpoints)</sup> (for blobs). 211 212A HEAD request to an existing blob or manifest URL MUST return `200 OK`. 213A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`. 214A successful response SHOULD contain the size in bytes of the uploaded blob in the header `Content-Length`. 215 216If the blob or manifest is not found in the repository, the response code MUST be `404 Not Found`. 217 218#### Push 219 220Pushing an object typically works in the opposite order as a pull: the blobs making up the object are uploaded first, and the manifest last. 221A useful diagram is provided [here](https://github.com/google/go-containerregistry/tree/d7f8d06c87ed209507dd5f2d723267fe35b38a9f/pkg/v1/remote#anatomy-of-an-image-upload). 222 223A registry MUST initially accept an otherwise valid manifest with a `subject` field that references a manifest that does not exist in the repository, allowing clients to push a manifest and referrers to that manifest in either order. 224A registry MAY reject a manifest uploaded to the manifest endpoint with descriptors in other fields that reference a manifest or blob that does not exist in the registry. 225When a manifest is rejected for this reason, it MUST result in one or more `MANIFEST_BLOB_UNKNOWN` errors <sup>[code-1](#error-codes)</sup>. 226 227##### Pushing blobs 228 229There are two ways to push blobs: chunked or monolithic. 230 231##### Pushing a blob monolithically 232 233There are two ways to push a blob monolithically: 2341. A `POST` request followed by a `PUT` request 2352. A single `POST` request 236 237--- 238 239###### POST then PUT 240 241To push a blob monolithically by using a POST request followed by a PUT request, there are two steps: 2421. Obtain a session id (upload URL) 2432. Upload the blob to said URL 244 245To obtain a session ID, perform a `POST` request to a URL in the following format: 246 247`/v2/<name>/blobs/uploads/` <sup>[end-4a](#endpoints)</sup> 248 249Here, `<name>` refers to the namespace of the repository. 250Upon success, the response MUST have a code of `202 Accepted`, and MUST include the following header: 251 252``` 253Location: <location> 254``` 255 256The `<location>` MUST contain a UUID representing a unique session ID for the upload to follow. 257The `<location>` does not necessarily need to be provided by the registry itself. 258In fact, offloading to another server can be a [better strategy](https://www.backblaze.com/blog/design-thinking-b2-apis-the-hidden-costs-of-s3-compatibility/). 259 260Optionally, the location MAY be absolute (containing the protocol and/or hostname), or it MAY be relative (containing just the URL path). 261For more information, see [RFC 7231](https://tools.ietf.org/html/rfc7231#section-7.1.2). 262 263Once the `<location>` has been obtained, perform the upload proper by making a `PUT` request to the following URL path, and with the following headers and body: 264 265`<location>?digest=<digest>` <sup>[end-6](#endpoints)</sup> 266``` 267Content-Length: <length> 268Content-Type: application/octet-stream 269``` 270``` 271<upload byte stream> 272``` 273 274The `<location>` MAY contain critical query parameters. 275Additionally, it SHOULD match exactly the `<location>` obtained from the `POST` request. 276It SHOULD NOT be assembled manually by clients except where absolute/relative conversion is necessary. 277 278Here, `<digest>` is the digest of the blob being uploaded, and `<length>` is its size in bytes. 279 280Upon successful completion of the request, the response MUST have code `201 Created` and MUST have the following header: 281 282``` 283Location: <blob-location> 284``` 285 286With `<blob-location>` being a pullable blob URL. 287 288--- 289 290###### Single POST 291 292Registries MAY support pushing blobs using a single POST request. 293 294To push a blob monolithically by using a single POST request, perform a `POST` request to a URL in the following form, and with the following headers and body: 295 296`/v2/<name>/blobs/uploads/?digest=<digest>` <sup>[end-4b](#endpoints)</sup> 297``` 298Content-Length: <length> 299Content-Type: application/octet-stream 300``` 301``` 302<upload byte stream> 303``` 304 305Here, `<name>` is the repository's namespace, `<digest>` is the blob's digest, and `<length>` is the size (in bytes) of the blob. 306 307The `Content-Length` header MUST match the blob's actual content length. 308Likewise, the `<digest>` MUST match the blob's digest. 309 310Registries that do not support single request monolithic uploads SHOULD return a `202 Accepted` status code and `Location` header and clients SHOULD proceed with a subsequent PUT request, as described by the [POST then PUT upload method](#post-then-put). 311 312Successful completion of the request MUST return a `201 Created` and MUST include the following header: 313 314``` 315Location: <blob-location> 316``` 317 318Here, `<blob-location>` is a pullable blob URL. 319This location does not necessarily have to be served by your registry, for example, in the case of a signed URL from some cloud storage provider that your registry generates. 320 321 322##### Pushing a blob in chunks 323 324A chunked blob upload is accomplished in three phases: 3251. Obtain a session ID (upload URL) (`POST`) 3262. Upload the chunks (`PATCH`) 3273. Close the session (`PUT`) 328 329For information on obtaining a session ID, reference the above section on pushing a blob monolithically via the `POST`/`PUT` method. 330The process remains unchanged for chunked upload, except that the post request MUST include the following header: 331 332``` 333Content-Length: 0 334``` 335 336If the registry has a minimum chunk size, the `POST` response SHOULD include the following header, where `<size>` is the size in bytes (see the blob `PATCH` definition for usage): 337 338``` 339OCI-Chunk-Min-Length: <size> 340``` 341 342Please reference the above section for restrictions on the `<location>`. 343 344--- 345To upload a chunk, issue a `PATCH` request to a URL path in the following format, and with the following headers and body: 346 347URL path: `<location>` <sup>[end-5](#endpoints)</sup> 348``` 349Content-Type: application/octet-stream 350Content-Range: <range> 351Content-Length: <length> 352``` 353``` 354<upload byte stream of chunk> 355``` 356 357The `<location>` refers to the URL obtained from the preceding `POST` request. 358 359The `<range>` refers to the byte range of the chunk, and MUST be inclusive on both ends. 360The first chunk's range MUST begin with `0`. 361It MUST match the following regular expression: 362 363```regexp 364^[0-9]+-[0-9]+$ 365``` 366 367The `<length>` is the content-length, in bytes, of the current chunk. 368If the registry provides an `OCI-Chunk-Min-Length` header in the `POST` response, the size of each chunk, except for the final chunk, SHOULD be greater or equal to that value. 369The final chunk MAY have any length. 370 371Each successful chunk upload MUST have a `202 Accepted` response code, and MUST have the following headers: 372 373``` 374Location: <location> 375Range: 0-<end-of-range> 376``` 377 378Each consecutive chunk upload SHOULD use the `<location>` provided in the response to the previous chunk upload. 379 380The `<end-of-range>` value is the position of the last uploaded byte. 381 382Chunks MUST be uploaded in order, with the first byte of a chunk being the last chunk's `<end-of-range>` plus one. 383If a chunk is uploaded out of order, the registry MUST respond with a `416 Requested Range Not Satisfiable` code. 384A GET request may be used to retrieve the current valid offset and upload location. 385 386The final chunk MAY be uploaded using a `PATCH` request or it MAY be uploaded in the closing `PUT` request. 387Regardless of how the final chunk is uploaded, the session MUST be closed with a `PUT` request. 388 389--- 390 391To close the session, issue a `PUT` request to a url in the following format, and with the following headers (and optional body, depending on whether or not the final chunk was uploaded already via a `PATCH` request): 392 393`<location>?digest=<digest>` 394``` 395Content-Length: <length of chunk, if present> 396Content-Range: <range of chunk, if present> 397Content-Type: application/octet-stream <if chunk provided> 398``` 399``` 400OPTIONAL: <final chunk byte stream> 401``` 402 403The closing `PUT` request MUST include the `<digest>` of the whole blob (not the final chunk) as a query parameter. 404 405The response to a successful closing of the session MUST be `201 Created`, and MUST contain the following header: 406``` 407Location: <blob-location> 408``` 409 410Here, `<blob-location>` is a pullable blob URL. 411 412--- 413 414To get the current status after a 416 error, issue a `GET` request to a URL `<location>` <sup>[end-13](#endpoints)</sup>. 415 416The `<location>` refers to the URL obtained from any preceding `POST` or `PATCH` request. 417 418The response to an active upload `<location>` MUST be a `204 No Content` response code, and MUST have the following headers: 419 420``` 421Location: <location> 422Range: 0-<end-of-range> 423``` 424 425The following chunk upload SHOULD use the `<location>` provided in the response. 426 427The `<end-of-range>` value is the position of the last uploaded byte. 428 429##### Mounting a blob from another repository 430 431If a necessary blob exists already in another repository within the same registry, it can be mounted into a different repository via a `POST` 432request in the following format: 433 434`/v2/<name>/blobs/uploads/?mount=<digest>&from=<other_name>` <sup>[end-11](#endpoints)</sup>. 435 436In this case, `<name>` is the namespace to which the blob will be mounted. 437`<digest>` is the digest of the blob to mount, and `<other_name>` is the namespace from which the blob should be mounted. 438This step is usually taken in place of the previously-described `POST` request to `/v2/<name>/blobs/uploads/` <sup>[end-4a](#endpoints)</sup> (which is used to initiate an upload session). 439 440The response to a successful mount MUST be `201 Created`, and MUST contain the following header: 441``` 442Location: <blob-location> 443``` 444 445The Location header will contain the registry URL to access the accepted layer file. 446The Docker-Content-Digest header returns the canonical digest of the uploaded blob which MAY differ from the provided digest. 447Most clients MAY ignore the value but if it is used, the client SHOULD verify the value against the uploaded blob data. 448 449The registry MAY treat the `from` parameter as optional, and it MAY cross-mount the blob if it can be found. 450 451Alternatively, if a registry does not support cross-repository mounting or is unable to mount the requested blob, it SHOULD return a `202`. 452This indicates that the upload session has begun and that the client MAY proceed with the upload. 453 454##### Pushing Manifests 455 456To push a manifest, perform a `PUT` request to a path in the following format, and with the following headers and body: `/v2/<name>/manifests/<reference>` <sup>[end-7](#endpoints)</sup> 457 458Clients SHOULD set the `Content-Type` header to the type of the manifest being pushed. 459The client SHOULD NOT include parameters on the `Content-Type` header (see [RFC7231](https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1)). 460The registry SHOULD ignore parameters on the `Content-Type` header. 461All manifests SHOULD include a `mediaType` field declaring the type of the manifest being pushed. 462If a manifest includes a `mediaType` field, clients MUST set the `Content-Type` header to the value specified by the `mediaType` field. 463 464``` 465Content-Type: application/vnd.oci.image.manifest.v1+json 466``` 467Manifest byte stream: 468``` 469{ 470 "mediaType": "application/vnd.oci.image.manifest.v1+json", 471 ... 472} 473``` 474 475`<name>` is the namespace of the repository, and the `<reference>` MUST be either a) a digest or b) a tag. 476 477The uploaded manifest MUST reference any blobs that make up the object. 478However, the list of blobs MAY be empty. 479 480The registry MUST store the manifest in the exact byte representation provided by the client. 481Upon a successful upload, the registry MUST return response code `201 Created`, and MUST have the following header: 482 483``` 484Location: <location> 485``` 486 487The `<location>` is a pullable manifest URL. 488The Docker-Content-Digest header returns the canonical digest of the uploaded blob, and MUST be equal to the client provided digest. 489Clients MAY ignore the value but if it is used, the client SHOULD verify the value against the uploaded blob data. 490 491An attempt to pull a nonexistent repository MUST return response code `404 Not Found`. 492 493A registry SHOULD enforce some limit on the maximum manifest size that it can accept. 494A registry that enforces this limit SHOULD respond to a request to push a manifest over this limit with a response code `413 Payload Too Large`. 495Client and registry implementations SHOULD expect to be able to support manifest pushes of at least 4 megabytes. 496 497###### Pushing Manifests with Subject 498 499When processing a request for an image manifest with the `subject` field, a registry implementation that supports the [referrers API](#listing-referrers) MUST respond with the response header `OCI-Subject: <subject digest>` to indicate to the client that the registry processed the request's `subject`. 500 501When pushing a manifest with the `subject` field and the `OCI-Subject` header was not set, the client MUST: 502 5031. Pull the current referrers list using the [referrers tag schema](#referrers-tag-schema). 5041. If that pull returns a manifest other than the expected image index, the client SHOULD report a failure and skip the remaining steps. 5051. If the tag returns a 404, the client MUST begin with an empty image index. 5061. Verify the descriptor for the manifest is not already in the referrers list (duplicate entries SHOULD NOT be created). 5071. Append a descriptor for the pushed manifest to the manifests in the referrers list. 508 The value of the `artifactType` MUST be set to the `artifactType` value in the pushed manifest, if present. 509 If the `artifactType` is empty or missing in a pushed image manifest, the value of `artifactType` MUST be set to the config descriptor `mediaType` value. 510 All annotations from the pushed manifest MUST be copied to this descriptor. 5111. Push the updated referrers list using the same [referrers tag schema](#referrers-tag-schema). 512 The client MAY use conditional HTTP requests to prevent overwriting a referrers list that has changed since it was first pulled. 513 514#### Content Discovery 515 516##### Listing Tags 517 518To fetch the list of tags, perform a `GET` request to a path in the following format: `/v2/<name>/tags/list` <sup>[end-8a](#endpoints)</sup> 519 520`<name>` is the namespace of the repository. 521Assuming a repository is found, this request MUST return a `200 OK` response code. 522The list of tags MAY be empty if there are no tags on the repository. 523If the list is not empty, the tags MUST be in lexical order (i.e. case-insensitive alphanumeric order). 524 525Upon success, the response MUST be a json body in the following format: 526```json 527{ 528 "name": "<name>", 529 "tags": [ 530 "<tag1>", 531 "<tag2>", 532 "<tag3>" 533 ] 534} 535``` 536 537`<name>` is the namespace of the repository, and `<tag1>`, `<tag2>`, and `<tag3>` are each tags on the repository. 538 539In addition to fetching the whole list of tags, a subset of the tags can be fetched by providing the `n` query parameter. 540In this case, the path will look like the following: `/v2/<name>/tags/list?n=<int>` <sup>[end-8b](#endpoints)</sup> 541 542`<name>` is the namespace of the repository, and `<int>` is an integer specifying the number of tags requested. 543The response to such a request MAY return fewer than `<int>` results, but only when the total number of tags attached to the repository is less than `<int>` or a `Link` header is provided. 544Otherwise, the response MUST include `<int>` results. 545A `Link` header MAY be included in the response when additional tags are available. 546If included, the `Link` header MUST be set according to [RFC5988](https://www.rfc-editor.org/rfc/rfc5988.html) with the Relation Type `rel="next"`. 547When `n` is zero, this endpoint MUST return an empty list, and MUST NOT include a `Link` header. 548Without the `last` query parameter (described next), the list returned will start at the beginning of the list and include `<int>` results. 549As above, the tags MUST be in lexical order. 550 551The `last` query parameter provides further means for limiting the number of tags. 552It is usually used in combination with the `n` parameter: `/v2/<name>/tags/list?n=<int>&last=<tagname>` <sup>[end-8b](#endpoints)</sup> 553 554`<name>` is the namespace of the repository, `<int>` is the number of tags requested, and `<tagname>` is the *value* of the last tag. 555`<tagname>` MUST NOT be a numerical index, but rather it MUST be a proper tag. 556A request of this sort will return up to `<int>` tags, beginning non-inclusively with `<tagname>`. 557That is to say, `<tagname>` will not be included in the results, but up to `<int>` tags *after* `<tagname>` will be returned. 558The tags MUST be in lexical order. 559 560When using the `last` query parameter, the `n` parameter is OPTIONAL. 561 562_Implementers note:_ 563Previous versions of this specification did not include the `Link` header. 564Clients depending on the number of tags returned matching `n` may prematurely stop pagination on registries using the `Link` header. 565When available, clients should prefer the `Link` header over using the `last` parameter for pagination. 566 567##### Listing Referrers 568 569*Note: this feature was added in distibution-spec 1.1. 570Registries should see [Enabling the Referrers API](#enabling-the-referrers-api) before enabling this.* 571 572To fetch the list of referrers, perform a `GET` request to a path in the following format: `/v2/<name>/referrers/<digest>` <sup>[end-12a](#endpoints)</sup>. 573 574`<name>` is the namespace of the repository, and `<digest>` is the digest of the manifest specified in the `subject` field. 575 576Assuming a repository is found, this request MUST return a `200 OK` response code. 577If the registry supports the referrers API, the registry MUST NOT return a `404 Not Found` to a referrers API requests. 578If the request is invalid, such as a `<digest>` with an invalid syntax, a `400 Bad Request` MUST be returned. 579 580Upon success, the response MUST be a JSON body with an image index containing a list of descriptors. 581The `Content-Type` header MUST be set to `application/vnd.oci.image.index.v1+json`. 582Each descriptor is of an image manifest or index in the same `<name>` namespace with a `subject` field that specifies the value of `<digest>`. 583The descriptors MUST include an `artifactType` field that is set to the value of the `artifactType` in the image manifest or index, if present. 584If the `artifactType` is empty or missing in the image manifest, the value of `artifactType` MUST be set to the config descriptor `mediaType` value. 585If the `artifactType` is empty or missing in an index, the `artifactType` MUST be omitted. 586The descriptors MUST include annotations from the image manifest or index. 587If a query results in no matching referrers, an empty manifest list MUST be returned. 588 589```json 590{ 591 "schemaVersion": 2, 592 "mediaType": "application/vnd.oci.image.index.v1+json", 593 "manifests": [ 594 { 595 "mediaType": "application/vnd.oci.image.manifest.v1+json", 596 "size": 1234, 597 "digest": "sha256:a1a1a1...", 598 "artifactType": "application/vnd.example.sbom.v1", 599 "annotations": { 600 "org.opencontainers.image.created": "2022-01-01T14:42:55Z", 601 "org.example.sbom.format": "json" 602 } 603 }, 604 { 605 "mediaType": "application/vnd.oci.image.manifest.v1+json", 606 "size": 1234, 607 "digest": "sha256:a2a2a2...", 608 "artifactType": "application/vnd.example.signature.v1", 609 "annotations": { 610 "org.opencontainers.image.created": "2022-01-01T07:21:33Z", 611 "org.example.signature.fingerprint": "abcd" 612 } 613 }, 614 { 615 "mediaType": "application/vnd.oci.image.index.v1+json", 616 "size": 1234, 617 "digest": "sha256:a3a3a3...", 618 "annotations": { 619 "org.opencontainers.image.created": "2023-01-01T07:21:33Z", 620 } 621 } 622 ] 623} 624``` 625 626A `Link` header MUST be included in the response when the descriptor list cannot be returned in a single manifest. 627Each response is an image index with different descriptors in the `manifests` field. 628The `Link` header MUST be set according to [RFC5988](https://www.rfc-editor.org/rfc/rfc5988.html) with the Relation Type `rel="next"`. 629 630The registry SHOULD support filtering on `artifactType`. 631To fetch the list of referrers with a filter, perform a `GET` request to a path in the following format: `/v2/<name>/referrers/<digest>?artifactType=<artifactType>` <sup>[end-12b](#endpoints)</sup>. 632If filtering is requested and applied, the response MUST include a header `OCI-Filters-Applied: artifactType` denoting that an `artifactType` filter was applied. 633If multiple filters are applied, the header MUST contain a comma separated list of applied filters. 634 635Example request with filtering: 636 637``` 638GET /v2/<name>/referrers/<digest>?artifactType=application/vnd.example.sbom.v1 639``` 640 641Example response with filtering: 642 643```json 644OCI-Filters-Applied: artifactType 645{ 646 "schemaVersion": 2, 647 "mediaType": "application/vnd.oci.image.index.v1+json", 648 "manifests": [ 649 { 650 "mediaType": "application/vnd.oci.image.manifest.v1+json", 651 "size": 1234, 652 "digest": "sha256:a1a1a1...", 653 "artifactType": "application/vnd.example.sbom.v1", 654 "annotations": { 655 "org.opencontainers.artifact.created": "2022-01-01T14:42:55Z", 656 "org.example.sbom.format": "json" 657 } 658 } 659 ], 660} 661``` 662 663If the [referrers API](#listing-referrers) returns a 404, the client MUST fallback to pulling the [referrers tag schema](#referrers-tag-schema). 664The response SHOULD be an image index with the same content that would be expected from the referrers API. 665If the response to the [referrers API](#listing-referrers) is a 404, and the tag schema does not return a valid image index, the client SHOULD assume there are no referrers to the manifest. 666 667#### Content Management 668 669Content management refers to the deletion of blobs, tags, and manifests. 670Registries MAY implement deletion or they MAY disable it. 671Similarly, a registry MAY implement tag deletion, while others MAY allow deletion only by manifest. 672 673##### Deleting tags 674 675To delete a tag, perform a `DELETE` request to a path in the following format: `/v2/<name>/manifests/<tag>` <sup>[end-9](#endpoints)</sup> 676 677`<name>` is the namespace of the repository, and `<tag>` is the name of the tag to be deleted. 678Upon success, the registry MUST respond with a `202 Accepted` code. 679If tag deletion is disabled, the registry MUST respond with either a `400 Bad Request` or a `405 Method Not Allowed`. 680 681Once deleted, a `GET` to `/v2/<name>/manifests/<tag>` will return a 404. 682 683##### Deleting Manifests 684 685To delete a manifest, perform a `DELETE` request to a path in the following format: `/v2/<name>/manifests/<digest>` <sup>[end-9](#endpoints)</sup> 686 687`<name>` is the namespace of the repository, and `<digest>` is the digest of the manifest to be deleted. 688Upon success, the registry MUST respond with a `202 Accepted` code. 689If the repository does not exist, the response MUST return `404 Not Found`. 690If manifest deletion is disabled, the registry MUST respond with either a `400 Bad Request` or a `405 Method Not Allowed`. 691 692Once deleted, a `GET` to `/v2/<name>/manifests/<digest>` and any tag pointing to that digest will return a 404. 693 694When deleting an image manifest that contains a `subject` field, and the [referrers API](#listing-referrers) returns a 404, clients SHOULD: 695 6961. Pull the referrers list using the [referrers tag schema](#referrers-tag-schema). 6971. Remove the descriptor entry from the array of manifests that references the deleted manifest. 6981. Push the updated referrers list using the same [referrers tag schema](#referrers-tag-schema). 699 The client MAY use conditional HTTP requests to prevent overwriting an referrers list that has changed since it was first pulled. 700 701When deleting a manifest that has an associated [referrers tag schema](#referrers-tag-schema), clients MAY also delete the referrers tag when it returns a valid image index. 702 703##### Deleting Blobs 704 705To delete a blob, perform a `DELETE` request to a path in the following format: `/v2/<name>/blobs/<digest>` <sup>[end-10](#endpoints)</sup> 706 707`<name>` is the namespace of the repository, and `<digest>` is the digest of the blob to be deleted. 708Upon success, the registry MUST respond with code `202 Accepted`. 709If the blob is not found, a `404 Not Found` code MUST be returned. 710If blob deletion is disabled, the registry MUST respond with either a `400 Bad Request` or a `405 Method Not Allowed`. 711 712### Backwards Compatibility 713 714Client implementations MUST support registries that implement partial or older versions of the OCI Distribution Spec. 715This section describes client fallback procedures that MUST be implemented when a new/optional API is not available from a registry. 716 717#### Unavailable Referrers API 718 719A client that pushes an image manifest with a defined `subject` field MUST verify the [referrers API](#listing-referrers) is available or fallback to updating the image index pushed to a tag described by the [referrers tag schema](#referrers-tag-schema). 720A client querying the [referrers API](#listing-referrers) and receiving a `404 Not Found` MUST fallback to using an image index pushed to a tag described by the [referrers tag schema](#referrers-tag-schema). 721 722##### Referrers Tag Schema 723 724```text 725<alg>-<ref> 726``` 727 728- `<alg>`: the digest algorithm (e.g. `sha256` or `sha512`) 729- `<ref>`: the digest from the `subject` field (limit of 64 characters) 730 731For example, a manifest with the `subject` field digest set to `sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` in the `registry.example.org/project` repository would have a descriptor in the referrers list at `registry.example.org/project:sha256-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`. 732 733This tag should return an image index matching the expected response of the [referrers API](#listing-referrers). 734Maintaining the content of this tag is the responsibility of clients pushing and deleting image manifests that contain a `subject` field. 735 736*Note*: multiple clients could attempt to update the tag simultaneously resulting in race conditions and data loss. 737Protection against race conditions is the responsibility of clients and end users, and can be resolved by using a registry that provides the [referrers API](#listing-referrers). 738Clients MAY use a conditional HTTP push for registries that support ETag conditions to avoid conflicts with other clients. 739 740### Upgrade Procedures 741 742The following describes procedures for upgrading to a newer version of the spec and the process to enable new APIs. 743 744#### Enabling the Referrers API 745 746The referrers API here is described by [Listing Referrers](#listing-referrers) and [end-12a](#endpoints). 747When registries add support for the referrers API, this API needs to account for manifests that were pushed before the API was available using the [Referrers Tag Schema](#referrers-tag-schema). 748 7491. Registries MUST include preexisting image manifests that are listed in an image index tagged with the [referrers tag schema](#referrers-tag-schema) and have a valid `subject` field in the referrers API response. 7501. Registries MAY include all preexisting image manifests with a `subject` field in the referrers API response. 7511. After the referrers API is enabled, Registries MUST include all newly pushed image manifests with a valid `subject` field in the referrers API response. 752 753### API 754 755The API operates over HTTP. Below is a summary of the endpoints used by the API. 756 757#### Determining Support 758 759To check whether or not the registry implements this specification, perform a `GET` request to the following endpoint: `/v2/` <sup>[end-1](#endpoints)</sup>. 760 761If the response is `200 OK`, then the registry implements this specification. 762 763This endpoint MAY be used for authentication/authorization purposes, but this is out of the purview of this specification. 764 765#### Endpoints 766 767| ID | Method | API Endpoint | Success | Failure | 768| ------- | -------------- | -------------------------------------------------------------- | ----------- | ----------------- | 769| end-1 | `GET` | `/v2/` | `200` | `404`/`401` | 770| end-2 | `GET` / `HEAD` | `/v2/<name>/blobs/<digest>` | `200` | `404` | 771| end-3 | `GET` / `HEAD` | `/v2/<name>/manifests/<reference>` | `200` | `404` | 772| end-4a | `POST` | `/v2/<name>/blobs/uploads/` | `202` | `404` | 773| end-4b | `POST` | `/v2/<name>/blobs/uploads/?digest=<digest>` | `201`/`202` | `404`/`400` | 774| end-5 | `PATCH` | `/v2/<name>/blobs/uploads/<reference>` | `202` | `404`/`416` | 775| end-6 | `PUT` | `/v2/<name>/blobs/uploads/<reference>?digest=<digest>` | `201` | `404`/`400` | 776| end-7 | `PUT` | `/v2/<name>/manifests/<reference>` | `201` | `404`/`413` | 777| end-8a | `GET` | `/v2/<name>/tags/list` | `200` | `404` | 778| end-8b | `GET` | `/v2/<name>/tags/list?n=<integer>&last=<tagname>` | `200` | `404` | 779| end-9 | `DELETE` | `/v2/<name>/manifests/<reference>` | `202` | `404`/`400`/`405` | 780| end-10 | `DELETE` | `/v2/<name>/blobs/<digest>` | `202` | `404`/`400`/`405` | 781| end-11 | `POST` | `/v2/<name>/blobs/uploads/?mount=<digest>&from=<other_name>` | `201`/`202` | `404` | 782| end-12a | `GET` | `/v2/<name>/referrers/<digest>` | `200` | `404`/`400` | 783| end-12b | `GET` | `/v2/<name>/referrers/<digest>?artifactType=<artifactType>` | `200` | `404`/`400` | 784| end-13 | `GET` | `/v2/<name>/blobs/uploads/<reference>` | `204` | `404` | 785 786#### Error Codes 787 788A `4XX` response code from the registry MAY return a body in any format. If the response body is in JSON format, it MUST 789have the following format: 790 791```json 792 { 793 "errors": [ 794 { 795 "code": "<error identifier, see below>", 796 "message": "<message describing condition>", 797 "detail": "<unstructured>" 798 }, 799 ... 800 ] 801 } 802``` 803 804The `code` field MUST be a unique identifier, containing only uppercase alphabetic characters and underscores. 805The `message` field is OPTIONAL, and if present, it SHOULD be a human readable string or MAY be empty. 806The `detail` field is OPTIONAL and MAY contain arbitrary JSON data providing information the client can use to resolve the issue. 807 808The `code` field MUST be one of the following: 809 810| ID | Code | Description | 811|-------- | ------------------------|------------------------------------------------------------| 812| code-1 | `BLOB_UNKNOWN` | blob unknown to registry | 813| code-2 | `BLOB_UPLOAD_INVALID` | blob upload invalid | 814| code-3 | `BLOB_UPLOAD_UNKNOWN` | blob upload unknown to registry | 815| code-4 | `DIGEST_INVALID` | provided digest did not match uploaded content | 816| code-5 | `MANIFEST_BLOB_UNKNOWN` | manifest references a manifest or blob unknown to registry | 817| code-6 | `MANIFEST_INVALID` | manifest invalid | 818| code-7 | `MANIFEST_UNKNOWN` | manifest unknown to registry | 819| code-8 | `NAME_INVALID` | invalid repository name | 820| code-9 | `NAME_UNKNOWN` | repository name not known to registry | 821| code-10 | `SIZE_INVALID` | provided length did not match content length | 822| code-11 | `UNAUTHORIZED` | authentication required | 823| code-12 | `DENIED` | requested access to the resource is denied | 824| code-13 | `UNSUPPORTED` | the operation is unsupported | 825| code-14 | `TOOMANYREQUESTS` | too many requests | 826 827#### Warnings 828 829Registry implementations MAY include informational warnings in `Warning` headers, as described in [RFC 7234](https://www.rfc-editor.org/rfc/rfc7234#section-5.5). 830 831If included, `Warning` headers MUST specify a `warn-code` of `299` and a `warn-agent` of `-`, and MUST NOT specify a `warn-date` value. 832 833A registry MUST NOT send more than 4096 bytes of warning data from all headers combined. 834 835Example warning headers: 836 837``` 838Warning: 299 - "Your auth token will expire in 30 seconds." 839Warning: 299 - "This registry endpoint is deprecated and will be removed soon." 840Warning: 299 - "This image is deprecated and will be removed soon." 841``` 842 843If a client receives `Warning` response headers, it SHOULD report the warnings to the user in an unobtrusive way. 844Clients SHOULD deduplicate warnings from multiple associated responses. 845In accordance with RFC 7234, clients MUST NOT take any automated action based on the presence or contents of warnings, only report them to the user. 846 847### Appendix 848 849The following is a list of documents referenced in this spec: 850 851| ID | Title | Description | 852| ------ | ----- | ----------- | 853| apdx-1 | [Docker Registry HTTP API V2](https://github.com/docker/distribution/blob/5cb406d511b7b9163bff9b6439072e4892e5ae3b/docs/spec/api.md) | The original document upon which this spec was based | 854| apdx-1 | [Details](https://github.com/opencontainers/distribution-spec/blob/ef28f81727c3b5e98ab941ae050098ea664c0960/detail.md) | Historical document describing original API endpoints and requests in detail | 855| apdx-2 | [OCI Image Spec - image](https://github.com/opencontainers/image-spec/blob/v1.0.1/manifest.md) | Description of an image manifest, defined by the OCI Image Spec | 856| apdx-3 | [OCI Image Spec - digests](https://github.com/opencontainers/image-spec/blob/v1.0.1/descriptor.md#digests) | Description of digests, defined by the OCI Image Spec | 857| apdx-4 | [OCI Image Spec - config](https://github.com/opencontainers/image-spec/blob/v1.0.1/config.md) | Description of configs, defined by the OCI Image Spec | 858| apdx-5 | [OCI Image Spec - descriptor](https://github.com/opencontainers/image-spec/blob/v1.0.1/descriptor.md) | Description of descriptors, defined by the OCI Image Spec | 859| apdx-6 | [OCI Image Spec - index](https://github.com/opencontainers/image-spec/blob/v1.0.1/image-index.md) | Description of image index, defined by the OCI Image Spec |