86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
"""Canary: the pinned gitleaks release remains downloadable and executable.
|
|
|
|
The gateway Dockerfile verifies this archive during an image build. Repeating
|
|
the upstream check weekly keeps registry/release drift out of normal pull
|
|
requests while proving that the pinned URL, architecture checksum, archive
|
|
shape, and binary still agree.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import os
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
import tarfile
|
|
import tempfile
|
|
import unittest
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
DOCKERFILE = ROOT / "Dockerfile.gateway"
|
|
|
|
|
|
def _docker_arg(text: str, name: str) -> str:
|
|
match = re.search(rf"^ARG {re.escape(name)}=(\S+)$", text, re.MULTILINE)
|
|
if match is None:
|
|
raise AssertionError(f"Dockerfile.gateway has no concrete ARG {name}")
|
|
return match.group(1)
|
|
|
|
|
|
@unittest.skipUnless(
|
|
os.environ.get("BOT_BOTTLE_RUN_CANARIES") == "1",
|
|
"canary suite is opt-in; set BOT_BOTTLE_RUN_CANARIES=1 to run",
|
|
)
|
|
class TestGitleaksRelease(unittest.TestCase):
|
|
def test_pinned_archive_checksum_and_binary(self) -> None:
|
|
dockerfile = DOCKERFILE.read_text(encoding="utf-8")
|
|
version = _docker_arg(dockerfile, "GITLEAKS_VERSION")
|
|
machine = platform.machine().lower()
|
|
architectures = {
|
|
"x86_64": ("linux_x64", "GITLEAKS_SHA256_AMD64"),
|
|
"amd64": ("linux_x64", "GITLEAKS_SHA256_AMD64"),
|
|
"aarch64": ("linux_arm64", "GITLEAKS_SHA256_ARM64"),
|
|
"arm64": ("linux_arm64", "GITLEAKS_SHA256_ARM64"),
|
|
}
|
|
if machine not in architectures:
|
|
self.fail(f"unsupported canary runner architecture: {machine}")
|
|
asset, checksum_arg = architectures[machine]
|
|
expected_checksum = _docker_arg(dockerfile, checksum_arg)
|
|
url = (
|
|
"https://github.com/gitleaks/gitleaks/releases/download/"
|
|
f"v{version}/gitleaks_{version}_{asset}.tar.gz"
|
|
)
|
|
|
|
with tempfile.TemporaryDirectory(prefix="bot-bottle-gitleaks-canary.") as tmp:
|
|
archive = Path(tmp) / "gitleaks.tar.gz"
|
|
urllib.request.urlretrieve(url, archive)
|
|
self.assertEqual(
|
|
expected_checksum,
|
|
hashlib.sha256(archive.read_bytes()).hexdigest(),
|
|
"the pinned upstream archive no longer matches Dockerfile.gateway",
|
|
)
|
|
with tarfile.open(archive, "r:gz") as bundle:
|
|
member = bundle.getmember("gitleaks")
|
|
source = bundle.extractfile(member)
|
|
if source is None:
|
|
self.fail("gitleaks archive member is not a regular file")
|
|
binary = Path(tmp) / "gitleaks"
|
|
binary.write_bytes(source.read())
|
|
binary.chmod(0o755)
|
|
result = subprocess.run(
|
|
[str(binary), "version"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
self.assertEqual(0, result.returncode, result.stderr)
|
|
self.assertIn(version, result.stdout + result.stderr)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|