supply chain: verify signatures and pins across image + kernel builds
Three independent hardenings, addressing a review finding that the kernel and image build pipelines were relying on HTTPS alone for artifact integrity. scripts/make-generic-kernel.sh - Fetch the detached PGP signature (linux-<ver>.tar.sign) alongside the tarball and verify it with gpg before extraction. An isolated $GNUPGHOME under the tempdir keeps the kernel signers out of the invoking user's keyring. - Import the three kernel.org release signing keys (Greg KH / Linus / Sasha Levin) from keyserver.ubuntu.com, falling back to keys.openpgp.org. Ubuntu comes first because keys.openpgp.org strips unverified UIDs on upload, leaving gpg with UID-less keys it refuses to trust. - Require VALIDSIG (cryptographic proof) rather than GOODSIG (printed even for expired keys) before proceeding. Verified end-to-end against a clean tarball (accepts) and a byte-flipped tampered copy (rejects with BADSIG). - gpg + gpgv + xz added to the required-tools check. images/golden/Dockerfile - Pin Docker's apt signing key by fingerprint. After downloading /etc/apt/keyrings/docker.asc we gpg --show-keys --with-colons it, extract the fpr, and compare against the expected 9DC858229FC7DD38854AE2D88D81803C0EBFCD88. A tampered or swapped key aborts the build before any apt repo metadata is fetched. - Replace `curl https://mise.run | sh` with a pinned GitHub release binary (mise v2026.4.18, linux-x64) verified against its published sha256. Refuses to build on unknown architectures rather than silently installing a binary we have no hash for. - Add gnupg to the ESSENTIAL apt-get install so the fingerprint check has gpg available. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
011b59a72f
commit
25a1466947
2 changed files with 109 additions and 23 deletions
|
|
@ -17,8 +17,9 @@ ENV DEBIAN_FRONTEND=noninteractive \
|
|||
# -------- 1. ESSENTIAL --------
|
||||
# Banger needs: an init (systemd + udev + dbus), sshd (the only
|
||||
# control channel), TLS roots + curl (first-boot installs + mise
|
||||
# installer), iproute2 (debugging; `ip` is still useful even when
|
||||
# the kernel sets IP via cmdline).
|
||||
# installer), gnupg (build-time signing-key verification for the
|
||||
# Docker apt repo), iproute2 (debugging; `ip` is still useful even
|
||||
# when the kernel sets IP via cmdline).
|
||||
#
|
||||
# udev is a Recommends of the systemd package on Debian. With
|
||||
# --no-install-recommends it's skipped — and without it systemd never
|
||||
|
|
@ -33,6 +34,7 @@ RUN apt-get update \
|
|||
openssh-server \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
iproute2 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
|
@ -55,25 +57,57 @@ RUN apt-get update \
|
|||
# Docker CE (with Compose v2 + buildx) from the official apt repo.
|
||||
# Nested-VM docker gives Compose workflows hostname/port isolation
|
||||
# per banger VM, which is a big part of the sandbox story.
|
||||
RUN install -m 0755 -d /etc/apt/keyrings \
|
||||
&& curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \
|
||||
&& chmod a+r /etc/apt/keyrings/docker.asc \
|
||||
&& printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable\n' \
|
||||
"$(dpkg --print-architecture)" > /etc/apt/sources.list.d/docker.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
#
|
||||
# The apt key is verified against its published fingerprint before
|
||||
# we commit it to the signed-by keyring, so a tampered download (or
|
||||
# a TLS compromise against download.docker.com) cannot silently
|
||||
# swap in an attacker-controlled signing key. Fingerprint source:
|
||||
# https://docs.docker.com/engine/install/debian/#install-using-the-repository
|
||||
RUN set -eu; \
|
||||
expected_fpr=9DC858229FC7DD38854AE2D88D81803C0EBFCD88; \
|
||||
install -m 0755 -d /etc/apt/keyrings; \
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg -o /tmp/docker.asc; \
|
||||
got="$(gpg --with-colons --show-keys --fingerprint /tmp/docker.asc | awk -F: '/^fpr:/ {print $10; exit}')"; \
|
||||
if [ "$got" != "$expected_fpr" ]; then \
|
||||
echo "docker apt key fingerprint mismatch: got $got, want $expected_fpr" >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
mv /tmp/docker.asc /etc/apt/keyrings/docker.asc; \
|
||||
chmod a+r /etc/apt/keyrings/docker.asc; \
|
||||
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable\n' \
|
||||
"$(dpkg --print-architecture)" > /etc/apt/sources.list.d/docker.list; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
docker-ce docker-ce-cli containerd.io \
|
||||
docker-buildx-plugin docker-compose-plugin \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
docker-buildx-plugin docker-compose-plugin; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# mise — per-repo version manager. Installed system-wide so the
|
||||
# bashrc activation reaches every shell.
|
||||
RUN curl -fsSL https://mise.run | MISE_INSTALL_PATH=/usr/local/bin/mise sh \
|
||||
&& chmod 0755 /usr/local/bin/mise \
|
||||
&& install -d /etc/profile.d \
|
||||
&& printf '%s\n' 'if [ -x /usr/local/bin/mise ]; then eval "$(/usr/local/bin/mise activate bash)"; fi' \
|
||||
> /etc/profile.d/mise.sh \
|
||||
&& chmod 0644 /etc/profile.d/mise.sh
|
||||
# mise — per-repo version manager. Installed from a pinned GitHub
|
||||
# release asset rather than `curl https://mise.run | sh` so a compromise
|
||||
# of the installer endpoint can't silently push arbitrary code into
|
||||
# the golden image.
|
||||
#
|
||||
# Update protocol: bump MISE_VERSION + MISE_SHA256 together. Source
|
||||
# for the hash is the `digest` field on the release asset from
|
||||
# `gh release view --repo jdx/mise --json assets`, or compute from
|
||||
# the downloaded file and cross-reference against SHASUMS256.txt on
|
||||
# the release page.
|
||||
ARG MISE_VERSION=v2026.4.18
|
||||
ARG MISE_SHA256_AMD64=6ae2d5f0f23a2f2149bc5d9bf264fe0922a1da843f1903e453516c462b23cc1f
|
||||
RUN set -eux; \
|
||||
arch="$(dpkg --print-architecture)"; \
|
||||
if [ "$arch" != "amd64" ]; then \
|
||||
echo "mise pin only tracks amd64; add a ${arch} hash to refresh" >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
curl -fsSL -o /tmp/mise "https://github.com/jdx/mise/releases/download/${MISE_VERSION}/mise-${MISE_VERSION}-linux-x64"; \
|
||||
echo "${MISE_SHA256_AMD64} /tmp/mise" | sha256sum -c -; \
|
||||
install -m 0755 /tmp/mise /usr/local/bin/mise; \
|
||||
rm /tmp/mise; \
|
||||
install -d /etc/profile.d; \
|
||||
printf '%s\n' 'if [ -x /usr/local/bin/mise ]; then eval "$(/usr/local/bin/mise activate bash)"; fi' \
|
||||
> /etc/profile.d/mise.sh; \
|
||||
chmod 0644 /etc/profile.d/mise.sh
|
||||
|
||||
# Default branch for any git init inside the sandbox.
|
||||
RUN git config --system init.defaultBranch main
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue