mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-02 06:58:52 +08:00
Pin Alpine amd64 to the verified upstream Node runtime without retaining temporary binaries in image layers. Bound fresh-process URL probes and verify serialized amd64/ARMv6 layers in CI. Keep existing Sequelize, SQLite and Debian runtime behavior unchanged.
45 lines
2.1 KiB
Python
45 lines
2.1 KiB
Python
"""Check serialized Docker layers, including files hidden by later deletions."""
|
|
|
|
import hashlib
|
|
import json
|
|
import sys
|
|
import tarfile
|
|
|
|
archive, architecture = sys.argv[1:]
|
|
assert architecture in {"amd64", "arm"}
|
|
nodes = []
|
|
with tarfile.open(archive) as image:
|
|
manifests = json.load(image.extractfile("manifest.json"))
|
|
assert len(manifests) == 1, "Expected one platform image"
|
|
manifest = manifests[0]
|
|
config = json.load(image.extractfile(manifest["Config"]))
|
|
assert config["architecture"] == architecture
|
|
for name in manifest["Layers"]:
|
|
with tarfile.open(fileobj=image.extractfile(name), mode="r|*") as layer:
|
|
for member in layer:
|
|
filename = member.name.removeprefix("./")
|
|
assert not (
|
|
filename == "tmp/node-runtime-amd64" and member.size > 0
|
|
), "Temporary amd64 Node remains in an immutable layer"
|
|
if filename not in {"usr/local/bin/node", "usr/bin/node"}:
|
|
continue
|
|
if not member.isfile():
|
|
continue
|
|
with layer.extractfile(member) as binary:
|
|
header = binary.read(20)
|
|
assert header[:4] == b"\x7fELF", "Expected a native Node binary"
|
|
digest = hashlib.sha256(header)
|
|
while chunk := binary.read(1024 * 1024):
|
|
digest.update(chunk)
|
|
endian = "little" if header[5] == 1 else "big"
|
|
machine = int.from_bytes(header[18:20], endian)
|
|
assert machine == {"amd64": 62, "arm": 40}[architecture], (
|
|
"Wrong Node architecture in an image layer"
|
|
)
|
|
nodes.append({"path": filename, "size": member.size, "sha256": digest.hexdigest()})
|
|
assert len(nodes) == 1, "Expected exactly one retained Node binary across all layers"
|
|
assert nodes[0]["path"] == (
|
|
"usr/local/bin/node" if architecture == "amd64" else "usr/bin/node"
|
|
)
|
|
print(json.dumps({"pass": True, "architecture": architecture, "layers": len(manifest["Layers"]), "nodes": nodes}))
|