Correct live image source pin and reconcile service attribution evidence
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
This commit is contained in:
parent
16c685f956
commit
fa64e4f868
7 changed files with 244 additions and 1 deletions
67
scripts/verify-packaged-source.py
Normal file
67
scripts/verify-packaged-source.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Compare retained OCI application bytes with exact Git commits, without startup.
|
||||
|
||||
No pull, mounts, network, application entrypoint, database or external writes.
|
||||
Inventory follows the runtime COPY instructions in this repo's Dockerfile.
|
||||
This proves packaged source equality, not dependency/build reproducibility.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
PROBE = """import hashlib,json,pathlib
|
||||
r=pathlib.Path('/app')
|
||||
f={str(p.relative_to(r)):hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
for p in (r/'coulomb_social').rglob('*')
|
||||
if p.is_file() and '__pycache__' not in p.parts and p.suffix != '.pyc'}
|
||||
for n in ['manage.py','pyproject.toml','docker-entrypoint.sh']:
|
||||
f[n]=hashlib.sha256((r/n).read_bytes()).hexdigest()
|
||||
print(json.dumps(f,sort_keys=True))
|
||||
"""
|
||||
|
||||
|
||||
def canonical(value):
|
||||
return json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
|
||||
|
||||
|
||||
def verify(image, sources):
|
||||
if not re.fullmatch(r"forgejo\.coulomb\.social/coulomb/"
|
||||
r"coulomb-social@sha256:[a-f0-9]{64}", image):
|
||||
raise ValueError("Exact retained application image digest required")
|
||||
if not sources or any(not re.fullmatch(r"[a-f0-9]{40}", source) for source in sources):
|
||||
raise ValueError("Full source commit hashes required")
|
||||
actual = json.loads(subprocess.check_output([
|
||||
"docker", "run", "--rm", "--pull=never", "--network", "none", "--read-only",
|
||||
"--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--entrypoint", "python",
|
||||
image, "-c", PROBE], timeout=60))
|
||||
comparisons = []
|
||||
for source in sources:
|
||||
paths = subprocess.check_output([
|
||||
"git", "ls-tree", "-r", "--name-only", source, "coulomb_social", "manage.py",
|
||||
"pyproject.toml", "scripts/docker-entrypoint.sh"], text=True).splitlines()
|
||||
expected = {}
|
||||
for name in paths:
|
||||
packaged = (name.removeprefix("scripts/")
|
||||
if name == "scripts/docker-entrypoint.sh" else name)
|
||||
expected[packaged] = hashlib.sha256(subprocess.check_output(
|
||||
["git", "show", source + ":" + name])).hexdigest()
|
||||
differences = sum(expected.get(n) != actual.get(n) for n in set(expected) | set(actual))
|
||||
comparisons.append({"commit": source, "packaged_file_count": len(actual),
|
||||
"source_file_count": len(expected), "different_files": differences,
|
||||
"all_packaged_source_bytes_match": differences == 0})
|
||||
return {"schema": "coulomb.packaged-source-provenance.v1", "image": image,
|
||||
"network": "none", "read_only_root": True, "entrypoint_bypassed": True,
|
||||
"database_contact": False, "production_changes": False, "comparisons": comparisons,
|
||||
"actual_packaged_manifest_sha256": hashlib.sha256(canonical(actual)).hexdigest(),
|
||||
"dependency_or_build_reproducibility_proved": False}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--image", required=True)
|
||||
parser.add_argument("--source", action="append", required=True)
|
||||
arguments = parser.parse_args()
|
||||
print(json.dumps(verify(arguments.image, arguments.source), indent=2))
|
||||
Loading…
Add table
Add a link
Reference in a new issue