25 lines
2.1 KiB
Python
25 lines
2.1 KiB
Python
"""Fingerprint actual supported runtime and verify every application lock pin."""
|
|
from pathlib import Path
|
|
import hashlib
|
|
import importlib.metadata
|
|
import json
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
lock=Path('/app/requirements-linux.lock')
|
|
pins=dict(re.findall(r'^([a-zA-Z0-9_.-]+)==([^\s;]+)',lock.read_text(),re.M))
|
|
installed={re.sub(r'[-_.]+','-',item.metadata['Name']).lower():item.version for item in importlib.metadata.distributions()}
|
|
assert len(pins)==55
|
|
assert all(installed[name]==version for name,version in pins.items())
|
|
assert not list(Path('/app').glob('.venv*')), 'Development environments leaked into built application image'
|
|
check=subprocess.run([sys.executable,'-m','pip','check'],capture_output=True,text=True)
|
|
assert check.returncode==0,check.stdout+check.stderr
|
|
import torch
|
|
import transformers
|
|
data=Path('/usr/share/tesseract-ocr/5/tessdata/eng.traineddata')
|
|
record={'status':'PASS','python':sys.version,'platform':platform.platform(),'libc':platform.libc_ver(),'applicationLockSha256':hashlib.sha256(lock.read_bytes()).hexdigest(),'applicationPins':pins,'installedDistributions':installed,'extrasOutsideApplicationLock':{name:version for name,version in installed.items() if name not in pins},'pipCheck':check.stdout.strip(),'noDevelopmentEnvironmentsInImage':True,'torchVersion':torch.__version__,'torchBuildCuda':torch.version.cuda,'cudaAvailable':torch.cuda.is_available(),'torchBuild':torch.__config__.show(),'tesseractVersion':subprocess.check_output(['tesseract','--version'],text=True).splitlines()[0],'englishOcrData':{'path':str(data),'bytes':data.stat().st_size,'sha256':hashlib.sha256(data.read_bytes()).hexdigest()},'nativePackages':subprocess.check_output(['dpkg-query','-W'],text=True),'scope':'Actual locally built source Dockerfile and exact55 locked application pins; test-only packages, if any, and bootstrap tools remain explicitly listed separately.'}
|
|
record['applicationSources']={name:hashlib.sha256((Path('/app')/name).read_bytes()).hexdigest() for name in ['app.py','parser_child.py','requirements.txt','requirements-linux.lock','tests/test_app.py']}
|
|
print(json.dumps(record),flush=True)
|