Files
server-deploy/scripts/probe-docker-repository.sh

56 lines
4.4 KiB
Bash

#!/usr/bin/env bash
# Local metadata-only probe. No APT changes or software installation.
set -euo pipefail
task_dir=$(mktemp -d /tmp/server-deploy-repository.XXXXXX)
chmod 700 "$task_dir"
base=https://download.docker.com/linux/ubuntu
curl --fail --silent --show-error --proto '=https' --max-time 45 --max-filesize 1048576 "$base/gpg" -o "$task_dir/docker.asc"
curl --fail --silent --show-error --proto '=https' --max-time 45 --max-filesize 1048576 "$base/dists/resolute/Release" -o "$task_dir/Release"
curl --fail --silent --show-error --proto '=https' --max-time 45 --max-filesize 65536 "$base/dists/resolute/Release.gpg" -o "$task_dir/Release.gpg"
curl --fail --silent --show-error --proto '=https' --max-time 45 --max-filesize 16777216 "$base/dists/resolute/stable/binary-amd64/Packages" -o "$task_dir/Packages"
gpg --batch --no-options --homedir "$task_dir" --with-colons --show-keys "$task_dir/docker.asc"
sha256sum "$task_dir/docker.asc"
gpg --batch --no-options --homedir "$task_dir" --dearmor --output "$task_dir/docker.gpg" "$task_dir/docker.asc"
gpgv --homedir "$task_dir" --keyring "$task_dir/docker.gpg" --status-fd 1 "$task_dir/Release.gpg" "$task_dir/Release"
head -n 12 "$task_dir/Release"
awk '/^Package: (docker-ce|docker-ce-cli|containerd.io|docker-buildx-plugin|docker-compose-plugin)$/ {name=$2} /^Version:/ && name!="" {print name, $2; name=""}' "$task_dir/Packages"
# Optional prebuilt local binary: verifies the same downloaded snapshots. This
# selects explicit fixture versions, not an installation or latest-version policy.
if [[ $# == 1 ]]; then
engine=$(awk '/^Package: docker-ce$/ {p=1} p && /^Version:/ {print $2; exit}' "$task_dir/Packages")
containerd=$(awk '/^Package: containerd.io$/ {p=1} p && /^Version:/ {print $2; exit}' "$task_dir/Packages")
buildx=$(awk '/^Package: docker-buildx-plugin$/ {p=1} p && /^Version:/ {print $2; exit}' "$task_dir/Packages")
compose=$(awk '/^Package: docker-compose-plugin$/ {p=1} p && /^Version:/ {print $2; exit}' "$task_dir/Packages")
for version in "$engine" "$containerd" "$buildx" "$compose"; do
[[ "$version" =~ ^[0-9A-Za-z.+:~_-]+$ ]] || exit 1
done
request=$(printf '{"directory":"%s","suite":"resolute","architecture":"amd64","versions":{"docker-ce":"%s","docker-ce-cli":"%s","containerd.io":"%s","docker-buildx-plugin":"%s","docker-compose-plugin":"%s"}}' "$task_dir" "$engine" "$engine" "$containerd" "$buildx" "$compose")
printf '%s\n' "$request" | "$1" verify-repository > "$task_dir/result.json"
python3 -I -c 'import json,sys; r=json.load(sys.stdin); p=sys.argv[1:]; assert r["repositoryAuthenticated"] is True; assert r["executable"] is False; assert r["packageBytesVerified"] is False; assert {x["name"]:x["version"] for x in r["lock"]["packages"]} == dict(zip(["docker-ce","docker-ce-cli","containerd.io","docker-buildx-plugin","docker-compose-plugin"],p)); assert len(r["lock"]["packages"])==5' "$engine" "$engine" "$containerd" "$buildx" "$compose" < "$task_dir/result.json"
cat "$task_dir/result.json"
if [[ -n "${DEPLOYCTL_TEST_GO:-}" ]]; then
DEPLOYCTL_REPOSITORY_FIXTURE="$task_dir" "$DEPLOYCTL_TEST_GO" test ./internal/aptrepo -run TestStagedSignatureIntegration -count=1 -v
fi
if [[ "${DEPLOYCTL_ONLINE_ARTIFACT_PROBE:-0}" == 1 ]]; then
bash scripts/probe-docker-artifacts.sh "$1" "$task_dir" "$request"
fi
cp -- "$task_dir/Packages" "$task_dir/Packages.original"
awk '/^SHA256:/ && !changed {c=substr($2,1,1); $2=(c=="0" ? "1" : "0") substr($2,2); changed=1} {print}' "$task_dir/Packages.original" > "$task_dir/Packages"
if printf '%s\n' "$request" | "$1" verify-repository > "$task_dir/rejected.json"; then
printf 'ERROR: tampered Packages accepted\n' >&2
exit 1
fi
[[ ! -s "$task_dir/rejected.json" ]]
mv -- "$task_dir/Packages.original" "$task_dir/Packages"
printf 'Tampered Packages rejected as expected.\n'
cp -- "$task_dir/Release" "$task_dir/Release.original"
awk '/^Date:/ {n=split($0,parts,":"); c=substr(parts[n],1,1); parts[n]=(c=="0" ? "1" : "0") substr(parts[n],2); line=parts[1]; for(i=2;i<=n;i++) line=line ":" parts[i]; print line; next} {print}' "$task_dir/Release.original" > "$task_dir/Release"
if printf '%s\n' "$request" | "$1" verify-repository > "$task_dir/rejected.json"; then
printf 'ERROR: tampered Release accepted\n' >&2
exit 1
fi
[[ ! -s "$task_dir/rejected.json" ]]
printf 'Tampered signed Release rejected as expected.\n'
fi
printf 'Local temporary probe directory: %s\n' "$task_dir"