From 11e3724919ab6d79fd6c424660669c60d2060aa5 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Wed, 20 Dec 2017 11:02:34 -0500 Subject: [PATCH] Return an http 415 (manifest version not supported) for OCI manifest content types This was breaking skopeo, as it first tries to send the *OCI* manifest type, which we didn't say we didn't support, thus breaking the tool --- endpoints/v2/manifest.py | 4 ++-- image/docker/schema2.py | 5 +++++ test/registry_tests.py | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/endpoints/v2/manifest.py b/endpoints/v2/manifest.py index c5e33662b..8c34e6fb5 100644 --- a/endpoints/v2/manifest.py +++ b/endpoints/v2/manifest.py @@ -18,7 +18,7 @@ from endpoints.v2.errors import (BlobUnknown, ManifestInvalid, ManifestUnknown, from endpoints.v2.labelhandlers import handle_label from image.docker import ManifestException from image.docker.schema1 import DockerSchema1Manifest, DockerSchema1ManifestBuilder -from image.docker.schema2 import DOCKER_SCHEMA2_CONTENT_TYPES +from image.docker.schema2 import DOCKER_SCHEMA2_CONTENT_TYPES, OCI_CONTENT_TYPES from notifications import spawn_notification from util.audit import track_and_log from util.names import VALID_TAG_PATTERN @@ -92,7 +92,7 @@ def fetch_manifest_by_digest(namespace_name, repo_name, manifest_ref): def _reject_manifest2_schema2(func): @wraps(func) def wrapped(*args, **kwargs): - if request.content_type in DOCKER_SCHEMA2_CONTENT_TYPES: + if request.content_type in (DOCKER_SCHEMA2_CONTENT_TYPES | OCI_CONTENT_TYPES): raise ManifestInvalid(detail={'message': 'manifest schema version not supported'}, http_status_code=415) return func(*args, **kwargs) diff --git a/image/docker/schema2.py b/image/docker/schema2.py index 504f5df80..2fa40a87c 100644 --- a/image/docker/schema2.py +++ b/image/docker/schema2.py @@ -7,5 +7,10 @@ https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md # Content Types DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE = 'application/vnd.docker.distribution.manifest.v2+json' DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE = 'application/vnd.docker.distribution.manifest.list.v2+json' + +OCI_MANIFEST_CONTENT_TYPE = 'application/vnd.oci.image.manifest.v1+json' +OCI_MANIFESTLIST_CONTENT_TYPE = 'application/vnd.oci.image.index.v1+json' + DOCKER_SCHEMA2_CONTENT_TYPES = {DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE, DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE} +OCI_CONTENT_TYPES = {OCI_MANIFEST_CONTENT_TYPE, OCI_MANIFESTLIST_CONTENT_TYPE} diff --git a/test/registry_tests.py b/test/registry_tests.py index f85cdb2a4..933062a6d 100644 --- a/test/registry_tests.py +++ b/test/registry_tests.py @@ -1623,6 +1623,26 @@ class V2RegistryTests(V2RegistryPullMixin, V2RegistryPushMixin, RegistryTestsMix headers={'Content-Type': 'application/vnd.docker.distribution.manifest.v2+json'}, auth='jwt') + def test_oci_manifest_type(self): + namespace = 'devtable' + repository = 'somerepo' + tag_name = 'sometag' + + repo_name = _get_repo_name(namespace, repository) + + self.v2_ping() + self.do_auth('devtable', 'password', namespace, repository, scopes=['push', 'pull']) + + # Build a fake manifest. + builder = DockerSchema1ManifestBuilder(namespace, repository, tag_name) + builder.add_layer('sha256:' + hashlib.sha256('invalid').hexdigest(), json.dumps({'id': 'foo'})) + manifest = builder.build(_JWK) + + self.conduct('PUT', '/v2/%s/manifests/%s' % (repo_name, tag_name), + data=manifest.bytes, expected_code=415, + headers={'Content-Type': 'application/vnd.oci.image.manifest.v1+json'}, + auth='jwt') + def test_invalid_blob(self): namespace = 'devtable' repository = 'somerepo'