Further fixes for unicode handling in manifests
We were occasionally trying to compute schema 2 version 1 signatures on the *unicode* representation, which was failing the signature check. This PR adds a new wrapper type called `Bytes`, which all manifests must take in, and which handles the unicodes vs encoded utf-8 stuff in a central location. This PR also adds a test for the manifest that was breaking in production.
This commit is contained in:
parent
05fa2bcbe0
commit
171c7e5238
28 changed files with 275 additions and 106 deletions
|
@ -12,6 +12,7 @@ from image.docker.schema2.list import DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE
|
|||
from image.docker.schemas import parse_manifest_from_bytes
|
||||
from test.registry.protocols import (RegistryProtocol, Failures, ProtocolOptions, PushResult,
|
||||
PullResult)
|
||||
from util.bytes import Bytes
|
||||
|
||||
|
||||
@unique
|
||||
|
@ -168,7 +169,8 @@ class V2Protocol(RegistryProtocol):
|
|||
|
||||
# Parse the returned manifest list and ensure it matches.
|
||||
assert response.headers['Content-Type'] == DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE
|
||||
retrieved = parse_manifest_from_bytes(response.text, response.headers['Content-Type'])
|
||||
retrieved = parse_manifest_from_bytes(Bytes.for_string_or_unicode(response.text),
|
||||
response.headers['Content-Type'])
|
||||
assert retrieved.schema_version == 2
|
||||
assert retrieved.is_manifest_list
|
||||
assert retrieved.digest == manifestlist.digest
|
||||
|
@ -184,7 +186,8 @@ class V2Protocol(RegistryProtocol):
|
|||
if expected_failure is not None:
|
||||
return None
|
||||
|
||||
manifest = parse_manifest_from_bytes(response.text, response.headers['Content-Type'])
|
||||
manifest = parse_manifest_from_bytes(Bytes.for_string_or_unicode(response.text),
|
||||
response.headers['Content-Type'])
|
||||
assert not manifest.is_manifest_list
|
||||
assert manifest.digest == manifest_digest
|
||||
|
||||
|
@ -221,7 +224,7 @@ class V2Protocol(RegistryProtocol):
|
|||
|
||||
self.conduct(session, 'PUT',
|
||||
'/v2/%s/manifests/%s' % (self.repo_name(namespace, repo_name), manifest.digest),
|
||||
data=manifest.bytes,
|
||||
data=manifest.bytes.as_encoded_str(),
|
||||
expected_status=(202, expected_failure, V2ProtocolSteps.PUT_MANIFEST),
|
||||
headers=manifest_headers)
|
||||
|
||||
|
@ -235,7 +238,7 @@ class V2Protocol(RegistryProtocol):
|
|||
|
||||
self.conduct(session, 'PUT',
|
||||
'/v2/%s/manifests/%s' % (self.repo_name(namespace, repo_name), tag_name),
|
||||
data=manifestlist.bytes,
|
||||
data=manifestlist.bytes.as_encoded_str(),
|
||||
expected_status=(202, expected_failure, V2ProtocolSteps.PUT_MANIFEST_LIST),
|
||||
headers=manifest_headers)
|
||||
|
||||
|
@ -282,10 +285,10 @@ class V2Protocol(RegistryProtocol):
|
|||
config['config'] = images[-1].config
|
||||
|
||||
config_json = json.dumps(config, ensure_ascii=options.ensure_ascii)
|
||||
schema2_config = DockerSchema2Config(config_json)
|
||||
schema2_config = DockerSchema2Config(Bytes.for_string_or_unicode(config_json))
|
||||
builder.set_config(schema2_config)
|
||||
|
||||
blobs[schema2_config.digest] = schema2_config.bytes.encode('utf-8')
|
||||
blobs[schema2_config.digest] = schema2_config.bytes.as_encoded_str()
|
||||
return builder.build(ensure_ascii=options.ensure_ascii)
|
||||
|
||||
def build_schema1(self, namespace, repo_name, tag_name, images, blobs, options):
|
||||
|
@ -372,7 +375,7 @@ class V2Protocol(RegistryProtocol):
|
|||
tag_or_digest = tag_name if not options.push_by_manifest_digest else manifest.digest
|
||||
self.conduct(session, 'PUT',
|
||||
'/v2/%s/manifests/%s' % (self.repo_name(namespace, repo_name), tag_or_digest),
|
||||
data=manifest.bytes.encode('utf-8'),
|
||||
data=manifest.bytes.as_encoded_str(),
|
||||
expected_status=(put_code, expected_failure, V2ProtocolSteps.PUT_MANIFEST),
|
||||
headers=manifest_headers)
|
||||
|
||||
|
@ -546,7 +549,8 @@ class V2Protocol(RegistryProtocol):
|
|||
if not self.schema2:
|
||||
assert response.headers['Content-Type'] in DOCKER_SCHEMA1_CONTENT_TYPES
|
||||
|
||||
manifest = parse_manifest_from_bytes(response.text, response.headers['Content-Type'])
|
||||
manifest = parse_manifest_from_bytes(Bytes.for_string_or_unicode(response.text),
|
||||
response.headers['Content-Type'])
|
||||
manifests[tag_name] = manifest
|
||||
|
||||
if manifest.schema_version == 1:
|
||||
|
|
Reference in a new issue