the-custodian/docs/changes/netkingdom-target-2026-10-17/inspect_public_image.py
codex 24ae04fa80
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Reject generated-only commits / generated-commit-guard (push) Waiting to run
docs: preserve reviewed NetKingdom session artifacts
2026-11-01 23:24:43 +01:00

103 lines
5.7 KiB
Python

"""Hash selected public image files without pulling, installing or running it."""
from pathlib import Path, PurePosixPath
import hashlib
import io
import json
import re
import tarfile
import time
import urllib.parse
import urllib.request
BASE = Path(__file__).resolve().parent
HOST = 'https://forgejo.coulomb.social'
IMAGE = '/v2/coulomb/state-hub/'
DIGEST = 'sha256:c802690ee1811b3d77df4077936f9cdced1385514e8673fcbc9232b84d645015'
DEADLINE = time.monotonic() + 180
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, *args, **kwargs):
raise RuntimeError('redirect_refused')
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect)
def get(path, limit, token=None, accept=None):
assert time.monotonic() < DEADLINE
headers = {}
if token:
headers['Authorization'] = 'Bearer ' + token
if accept:
headers['Accept'] = accept
with opener.open(urllib.request.Request(HOST + path, headers=headers), timeout=30) as response:
raw = response.read(limit + 1)
assert len(raw) <= limit
return raw
query = urllib.parse.urlencode({'service': 'container_registry', 'scope': 'repository:coulomb/state-hub:pull'})
auth = json.loads(get('/v2/token?' + query, 65536))
token = auth.get('token', auth.get('access_token'))
assert isinstance(token, str) and 0 < len(token) < 60000
raw = get(IMAGE + 'manifests/' + DIGEST, 1048576, token,
'application/vnd.docker.distribution.manifest.v2+json')
assert 'sha256:' + hashlib.sha256(raw).hexdigest() == DIGEST
manifest = json.loads(raw)
assert manifest['schemaVersion'] == 2 and len(manifest['layers']) <= 80
assert sum(x['size'] for x in manifest['layers']) <= 500 * 1024**2
files, packages, layers = {}, {}, []
for layer in manifest['layers']:
pin = layer['digest']
assert re.fullmatch('sha256:[0-9a-f]{64}', pin) and 0 <= layer['size'] <= 160 * 1024**2
blob = get(IMAGE + 'blobs/' + pin, layer['size'], token)
assert len(blob) == layer['size'] and 'sha256:' + hashlib.sha256(blob).hexdigest() == pin
with tarfile.open(fileobj=io.BytesIO(blob), mode='r|*') as archive:
count = 0
for entry in archive:
count += 1
assert count <= 100000 and time.monotonic() < DEADLINE
path = entry.name.removeprefix('./')
assert not path.startswith('/') and '..' not in PurePosixPath(path).parts
parent, _, basename = path.rpartition('/')
# Apply OCI deletions to the selected metadata view.
if basename.startswith('.wh.'):
erased = parent + '/' + basename[4:]
for key in list(files):
if key == erased or key.startswith(erased + '/'):
del files[key]
for key in list(packages):
if key == erased or key.startswith(erased + '/'):
del packages[key]
continue
code = (path == 'app/api/services/historical_projection.py'
or path.startswith('app/migrations/versions/') and path.endswith('.py')
or '/site-packages/hub_core/' in path and path.endswith('.py')
or path.startswith('tmp/hub-core/hub_core/') and path.endswith('.py')
or path == 'tmp/.ci-build-id')
metadata = '/site-packages/' in path and path.endswith('.dist-info/METADATA')
if not code and not metadata:
continue
assert entry.isfile() and entry.size <= 2 * 1024**2
stream = archive.extractfile(entry)
content = stream.read(2 * 1024**2 + 1)
assert len(content) == entry.size
if code:
files[path] = 'sha256:' + hashlib.sha256(content).hexdigest()
if metadata:
text = content.decode('utf-8')
name = re.findall(r'^Name: ([A-Za-z0-9_.-]+)$', text, re.M)
version = re.findall(r'^Version: ([A-Za-z0-9_.+!-]+)$', text, re.M)
assert len(name) == len(version) == 1
packages[path] = {'name': name[0], 'version': version[0],
'metadata_sha256': 'sha256:' + hashlib.sha256(content).hexdigest()}
layers.append({'digest': pin, 'compressed_bytes': len(blob), 'archive_entries': count})
del blob
expected = 'sha256:' + hashlib.sha256(Path('/home/worsch/state-hub/api/services/historical_projection.py').read_bytes()).hexdigest()
assert files.get('app/api/services/historical_projection.py') == expected
assert files.get('tmp/.ci-build-id') == 'sha256:' + hashlib.sha256(b'51bc70d\n').hexdigest()
migration = 'app/migrations/versions/c4d5e6f7a8b9_inbox_feed_revision.py'
assert files.get(migration) == 'sha256:48f1730037be99b5623e878d7f20a06bec243ce27317fde81c82e16006d7b3ce'
del auth, token
result = {'schema': 'statehub.public-image-inspection.v1', 'status': 'verified_selected_image_files',
'source_revision': '51bc70d1ff8f25450a8650d8e50caf053093a02e', 'image_digest': DIGEST,
'anonymous_protocol_only': True, 'token_retained': False, 'image_executed': False,
'image_installed_or_daemon_pulled': False, 'layers': layers, 'files': files,
'python_package_metadata': packages,
'limitations': ['Selected code and package metadata inventory; no full application acceptance or hermetic build provenance.',
'Floating dependency origins remain unknown; observed bytes and versions are bound to this immutable image digest.']}
(BASE / 'statehub-public-image-inspection.json').write_text(json.dumps(result, indent=2) + '\n')
print(json.dumps({'status': result['status'], 'layers': len(layers), 'selected_files': len(files), 'packages': len(packages)}))