Skip to content

Commit

Permalink
Remove v1 schema support
Browse files Browse the repository at this point in the history
  • Loading branch information
davedoesdev committed Jun 15, 2024
1 parent 1c4b9f8 commit 880aa9b
Show file tree
Hide file tree
Showing 17 changed files with 83 additions and 276 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Python module and command-line tool for storing and retrieving data in a Docker
- Store arbitrary data (blob-store)
- Content addressable
- Set up named aliases to blobs
- Supports Docker registry schemas v1 and v2
- Supports Docker registry schema v2
- Works on Python 3.7+

Please note that `dxf` does _not_ generate Docker container configuration,
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Docker registry.
- Store arbitrary data (blob-store)
- Content addressable
- Set up named aliases to blobs
- Supports Docker registry schemas v1 and v2
- Supports Docker registry schema v2
- Works on Python 3.7+

Please note that ``dxf`` does *not* generate Docker container
Expand Down
Binary file modified docs/_build/doctrees/environment.pickle
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/_build/html/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 6c8c4c6f0d5de4f2cf55fc05c2d0537c
config: 8732eab962e5b670c69842664f2c425a
tags: 645f666f9bcd5a90fca523b33c5a78b7
2 changes: 1 addition & 1 deletion docs/_build/html/_static/documentation_options.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const DOCUMENTATION_OPTIONS = {
VERSION: '11.5.0',
VERSION: '12.0.0',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',
Expand Down
8 changes: 4 additions & 4 deletions docs/_build/html/genindex.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; python-dxf 11.5.0 documentation</title>
<title>Index &#8212; python-dxf 12.0.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="_static/nature.css?v=0f882399" />
<script src="_static/documentation_options.js?v=a3d8d2de"></script>
<script src="_static/documentation_options.js?v=12c8f029"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="#" />
Expand All @@ -22,7 +22,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Index</a></li>
</ul>
</div>
Expand Down Expand Up @@ -259,7 +259,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Index</a></li>
</ul>
</div>
Expand Down
8 changes: 4 additions & 4 deletions docs/_build/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />

<title>dxf module &#8212; python-dxf 11.5.0 documentation</title>
<title>dxf module &#8212; python-dxf 12.0.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="_static/nature.css?v=0f882399" />
<script src="_static/documentation_options.js?v=a3d8d2de"></script>
<script src="_static/documentation_options.js?v=12c8f029"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="genindex.html" />
Expand All @@ -23,7 +23,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="#">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="#">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">dxf module</a></li>
</ul>
</div>
Expand Down Expand Up @@ -695,7 +695,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="#">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="#">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">dxf module</a></li>
</ul>
</div>
Expand Down
Binary file modified docs/_build/html/objects.inv
Binary file not shown.
8 changes: 4 additions & 4 deletions docs/_build/html/py-modindex.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Python Module Index &#8212; python-dxf 11.5.0 documentation</title>
<title>Python Module Index &#8212; python-dxf 12.0.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="_static/nature.css?v=0f882399" />
<script src="_static/documentation_options.js?v=a3d8d2de"></script>
<script src="_static/documentation_options.js?v=12c8f029"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="genindex.html" />
Expand All @@ -25,7 +25,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="#" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python Module Index</a></li>
</ul>
</div>
Expand Down Expand Up @@ -89,7 +89,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="#" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python Module Index</a></li>
</ul>
</div>
Expand Down
8 changes: 4 additions & 4 deletions docs/_build/html/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; python-dxf 11.5.0 documentation</title>
<title>Search &#8212; python-dxf 12.0.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="_static/nature.css?v=0f882399" />

<script src="_static/documentation_options.js?v=a3d8d2de"></script>
<script src="_static/documentation_options.js?v=12c8f029"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/searchtools.js"></script>
Expand All @@ -29,7 +29,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Search</a></li>
</ul>
</div>
Expand Down Expand Up @@ -86,7 +86,7 @@ <h3>Navigation</h3>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 11.5.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-0"><a href="index.html">python-dxf 12.0.0 documentation</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Search</a></li>
</ul>
</div>
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
# built documents.
#
# The short X.Y version.
version = '11.5'
version = '12.0'
# The full version, including alpha/beta/rc tags.
release = '11.5.0'
release = '12.0.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
153 changes: 3 additions & 150 deletions dxf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,19 +566,9 @@ def set_alias(self, alias: str, *digests: str) -> str:
:returns: The registry manifest used to define the alias. You almost definitely won't need this.
"""
try:
manifest_json = self.make_manifest(*digests)
self.set_manifest(alias, manifest_json)
return manifest_json
except requests.exceptions.HTTPError as ex:
# pylint: disable=no-member
if ex.response is None or \
ex.response.status_code != requests.codes.bad_request:
raise
manifest_json = self.make_unsigned_manifest(alias, *digests)
signed_json = _sign_manifest(manifest_json)
self._request('put', 'manifests/' + alias, data=signed_json)
return signed_json
manifest_json = self.make_manifest(*digests)
self.set_manifest(alias, manifest_json)
return manifest_json

def get_manifest_and_response(self, alias: str) -> Tuple[str, requests.Response]:
"""
Expand Down Expand Up @@ -630,26 +620,6 @@ def _get_alias(self, alias, manifest, verify, sizes, get_digest, get_dcd, get_ma

parsed_manifest = json.loads(manifest)

if parsed_manifest['schemaVersion'] == 1:
# https://github.com/docker/distribution/issues/1662#issuecomment-213101772
# "A schema1 manifest should always produce the same image id but
# defining the steps to produce directly from the manifest is not
# straight forward."
if get_digest:
raise exceptions.DXFDigestNotAvailableForSchema1()
r = _verify_manifest(manifest,
parsed_manifest,
dcd,
verify,
get_dcd)
if get_dcd:
r, dcd = r
if get_manifest:
r = manifest
else:
r = [(dgst, self.blob_size(dgst)) for dgst in r] if sizes else r
return (r, dcd) if get_dcd else r

if content is not None:
if dcd is not None:
method, expected_dgst = split_digest(dcd)
Expand Down Expand Up @@ -822,120 +792,3 @@ def from_base(cls: Type[TD], base: 'DXFBase', repo: str) -> TD:
r._headers = base._headers
r._sessions = [base._sessions[0]]
return r

# v1 schema support functions below

def make_unsigned_manifest(self, alias, *digests):
return json.dumps({
'schemaVersion': 1,
'name': self._repo,
'tag': alias,
'fsLayers': [{'blobSum': dgst} for dgst in digests],
'history': [{'v1Compatibility': '{}'} for dgst in digests]
}, sort_keys=True)

def _urlsafe_b64encode(s):
return base64.urlsafe_b64encode(_to_bytes_2and3(s)).rstrip(b'=').decode('utf-8')

def _pad64(s):
return s + b'=' * (-len(s) % 4)

def _urlsafe_b64decode(s):
return base64.urlsafe_b64decode(_pad64(_to_bytes_2and3(s)))

def _import_key(expkey):
if expkey['kty'] != 'EC':
raise exceptions.DXFUnexpectedKeyTypeError(expkey['kty'], 'EC')
if expkey['crv'] != 'P-256':
raise exceptions.DXFUnexpectedKeyTypeError(expkey['crv'], 'P-256')
return jwk.JWK(kty='EC', crv='P-256', x=expkey['x'], y=expkey['y'])

def _sign_manifest(manifest_json):
format_length = manifest_json.rfind('}')
format_tail = manifest_json[format_length:]
key = jwk.JWK.generate(kty='EC', crv='P-256')
jwstoken = jws.JWS(manifest_json.encode('utf-8'))
jkey = json.loads(key.export_public())
# Docker expects 32 bytes for x and y
jkey['x'] = _urlsafe_b64encode(_urlsafe_b64decode(jkey['x']).rjust(32, b'\0'))
jkey['y'] = _urlsafe_b64encode(_urlsafe_b64decode(jkey['y']).rjust(32, b'\0'))
jwstoken.add_signature(key, None, {
'formatLength': format_length,
'formatTail': _urlsafe_b64encode(format_tail)
}, {
'jwk': jkey,
'alg': 'ES256'
})
return manifest_json[:format_length] + \
', "signatures": [' + jwstoken.serialize() + ']' + \
format_tail

def _verify_manifest(content,
manifest,
content_digest,
verify,
get_content_digest):
# pylint: disable=too-many-locals,too-many-branches

# Adapted from https://github.com/joyent/node-docker-registry-client

if verify or ('signatures' in manifest):
signatures = []
for sig in manifest['signatures']:
protected64 = sig['protected']
protected = _urlsafe_b64decode(protected64).decode('utf-8')
protected_header = json.loads(protected)

format_length = protected_header['formatLength']
format_tail64 = protected_header['formatTail']
format_tail = _urlsafe_b64decode(format_tail64).decode('utf-8')

alg = sig['header']['alg']
if alg.lower() == 'none':
raise exceptions.DXFDisallowedSignatureAlgorithmError('none')
if sig['header'].get('chain'):
raise exceptions.DXFSignatureChainNotImplementedError()

signatures.append({
'alg': alg,
'signature': sig['signature'],
'protected64': protected64,
'key': _import_key(sig['header']['jwk']),
'format_length': format_length,
'format_tail': format_tail
})

payload = content[:signatures[0]['format_length']] + \
signatures[0]['format_tail']
payload64 = _urlsafe_b64encode(payload)
else:
payload = content

if content_digest:
method, expected_dgst = split_digest(content_digest)
hasher = hashlib.new(method)
hasher.update(payload.encode('utf-8'))
dgst = hasher.hexdigest()
if dgst != expected_dgst:
raise exceptions.DXFDigestMismatchError(
method + ':' + dgst,
method + ':' + expected_dgst)
elif get_content_digest:
content_digest = hash_bytes(payload.encode('utf-8'))

if verify:
for sig in signatures:
jwstoken = jws.JWS()
jwstoken.deserialize(json.dumps({
'payload': payload64, # pylint: disable=possibly-used-before-assignment
'protected': sig['protected64'],
'signature': sig['signature']
}), sig['key'], sig['alg'])

dgsts = []
for layer in manifest['fsLayers']:
dgst = layer['blobSum']
split_digest(dgst)
dgsts.append(dgst)

return (dgsts, content_digest) if get_content_digest else dgsts
Loading

0 comments on commit 880aa9b

Please sign in to comment.