"""Public distro dependencies and exact native artifact; no host runtime data.""" import hashlib import io import ipaddress import json from pathlib import Path import socket import subprocess import sys import tarfile repo,previous,out=map(Path,sys.argv[1:]) out.mkdir(mode=0o700) manifest=json.loads((previous/'native-artifact-sha256.json').read_text()) expected=manifest['usr/local/bin/archipelago']['sha256'] assert hashlib.sha256((previous/'normal-elf').read_bytes()).hexdigest()==expected files={Path('/usr/sbin/nft'), Path('/usr/lib/x86_64-linux-gnu/libpython3.13.so.1.0')} for binary in tuple(files): for word in subprocess.check_output(['ldd',str(binary)],text=True).split(): if word.startswith('/'): files.add(Path(word)) hashes={} with tarfile.open(out/'dependencies.tar','x') as archive: for path in sorted(files): source=path.resolve(strict=True) for entry in (source,*source.parents): meta=entry.stat() assert meta.st_uid==0 and not meta.st_mode&0o022 raw=source.read_bytes();hashes[str(path)]=hashlib.sha256(raw).hexdigest() info=tarfile.TarInfo(str(path).lstrip('/'));info.size=len(raw);info.mode=0o755 archive.addfile(info,io.BytesIO(raw)) addresses={name:sorted({str(ipaddress.ip_address(row[4][0])) for row in socket.getaddrinfo(name,4460,type=socket.SOCK_STREAM)}) for name in ('time.cloudflare.com','nts.netnod.se')} rules=['table inet c01_nts {','chain input { type filter hook input priority 0; policy drop; iifname "lo" accept; ct state established,related accept; }', 'chain forward { type filter hook forward priority 0; policy drop; }', 'chain output { type filter hook output priority 0; policy drop; oifname "lo" accept; ct state established,related accept;'] for addr in sorted(set(sum(addresses.values(),[]))): family='ip6' if ipaddress.ip_address(addr).version==6 else 'ip' rules += [f'{family} daddr {addr} tcp dport 4460 accept;',f'{family} daddr {addr} udp dport 123 accept;'] rules += ['}','}'] (out/'egress.nft').write_text('\n'.join(rules)+'\n') for name,source in [('probe.py','scripts/tests/c01_nts_disposable.py'),('c01_nts.py','scripts/c01_nts.py')]: raw=(repo/source).read_bytes();(out/name).write_bytes(raw);hashes[source]=hashlib.sha256(raw).hexdigest() if name=='c01_nts.py': assert raw==(previous/'source'/source).read_bytes(), 'collector differs from native build source' (out/'source.json').write_text(json.dumps({'files':hashes,'native_sha256':expected,'native_receipt':str(previous), 'addresses':addresses},indent=2)+'\n') (out/'containers.conf').write_text('[containers]\nkeyring=false\n')