test(canary): verify the pinned gitleaks release
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
# digest, etc.) without coupling every dev push to upstream registry
|
||||
# availability.
|
||||
#
|
||||
# Opt-in via CLAUDE_BOTTLE_RUN_CANARIES=1 so the same files can be run
|
||||
# Opt-in via BOT_BOTTLE_RUN_CANARIES=1 so the same files can be run
|
||||
# locally with the same gating.
|
||||
|
||||
name: canaries
|
||||
@@ -25,4 +25,7 @@ jobs:
|
||||
# No actions/setup-python: canaries are stdlib unittest on the image's
|
||||
# system Python 3.12 (older act_runner mishandles setup-python's PATH).
|
||||
- name: Run canaries
|
||||
run: python3 -m unittest discover -t . -s tests/canaries -v
|
||||
run: |
|
||||
python3 -m scripts.unittest_gate \
|
||||
-t . -s tests/canaries -v \
|
||||
--minimum-executed 1 --fail-on-skip
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user