fix: harden release validation
This commit is contained in:
@@ -15,8 +15,8 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: false
|
||||
|
||||
@@ -21,7 +21,7 @@ build() {
|
||||
output="$out/proxyctl-linux-$arch"
|
||||
(
|
||||
cd "$repo"
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \
|
||||
GOENV=off GOFLAGS= CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \
|
||||
go build -mod=readonly -buildvcs=false -trimpath \
|
||||
-ldflags="-s -w -X main.version=$VERSION" \
|
||||
-o "$output" ./cmd/proxyctl
|
||||
|
||||
@@ -5,21 +5,31 @@ repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
|
||||
work=$(mktemp -d)
|
||||
trap 'rm -rf "$work"' EXIT HUP INT TERM
|
||||
|
||||
snapshot_path() {
|
||||
path=$1
|
||||
if [ ! -e "$path" ] && [ ! -L "$path" ]; then
|
||||
printf 'absent\t%s\n' "$path"
|
||||
return
|
||||
fi
|
||||
|
||||
# Keep traversal, metadata collection, hashing, and sorting as separate
|
||||
# commands so set -e observes every failure without relying on pipefail.
|
||||
find -H "$path" -xdev \
|
||||
-exec stat --printf='metadata\t%F\t%a\t%u\t%g\t%N\n' -- {} + \
|
||||
>"$work/snapshot-metadata"
|
||||
LC_ALL=C sort "$work/snapshot-metadata"
|
||||
find -H "$path" -xdev -type f -exec sha256sum -- {} + \
|
||||
>"$work/snapshot-content"
|
||||
LC_ALL=C sort "$work/snapshot-content"
|
||||
}
|
||||
|
||||
snapshot() {
|
||||
for path in \
|
||||
"$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.docker/config.json" \
|
||||
/etc/apt/apt.conf.d /etc/docker/daemon.json /var/lib/proxyctl \
|
||||
/etc/systemd/system/docker.service.d
|
||||
do
|
||||
if [ -d "$path" ]; then
|
||||
find "$path" -type f -print0 2>/dev/null | sort -z | xargs -0 -r sha256sum 2>/dev/null || ls -ld "$path"
|
||||
elif [ -r "$path" ]; then
|
||||
sha256sum "$path"
|
||||
elif [ -e "$path" ]; then
|
||||
ls -ld "$path"
|
||||
else
|
||||
printf 'absent %s\n' "$path"
|
||||
fi
|
||||
snapshot_path "$path"
|
||||
done
|
||||
if command -v gsettings >/dev/null 2>&1; then
|
||||
gsettings list-recursively org.gnome.system.proxy 2>&1 || true
|
||||
|
||||
@@ -5,15 +5,52 @@ repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
|
||||
work=$(mktemp -d)
|
||||
trap 'rm -rf "$work"' EXIT HUP INT TERM
|
||||
|
||||
assert_no_process_test_seam() {
|
||||
artifact=$1
|
||||
if LC_ALL=C grep -a -F \
|
||||
-e 'proxyctl_process_test' \
|
||||
-e 'PROXYCTL_PROCESS_TEST_HOME' \
|
||||
"$artifact" >/dev/null
|
||||
then
|
||||
printf 'release artifact contains the process-test seam: %s\n' "$artifact" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/first"
|
||||
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/second"
|
||||
GOFLAGS='-tags=proxyctl_process_test' \
|
||||
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/malicious-goflags"
|
||||
printf 'GOFLAGS=-tags=proxyctl_process_test\n' >"$work/malicious-goenv"
|
||||
GOENV="$work/malicious-goenv" \
|
||||
VERSION=v1.0.0 "$repo/scripts/build-release.sh" "$work/malicious-goenv-build"
|
||||
|
||||
for arch in amd64 arm64; do
|
||||
binary="proxyctl-linux-$arch"
|
||||
test -x "$work/first/$binary"
|
||||
cmp "$work/first/$binary" "$work/second/$binary"
|
||||
cmp "$work/first/$binary" "$work/malicious-goflags/$binary"
|
||||
cmp "$work/first/$binary" "$work/malicious-goenv-build/$binary"
|
||||
assert_no_process_test_seam "$work/first/$binary"
|
||||
assert_no_process_test_seam "$work/malicious-goflags/$binary"
|
||||
assert_no_process_test_seam "$work/malicious-goenv-build/$binary"
|
||||
done
|
||||
cmp "$work/first/SHA256SUMS" "$work/second/SHA256SUMS"
|
||||
cmp "$work/first/SHA256SUMS" "$work/malicious-goflags/SHA256SUMS"
|
||||
cmp "$work/first/SHA256SUMS" "$work/malicious-goenv-build/SHA256SUMS"
|
||||
|
||||
(
|
||||
cd "$repo"
|
||||
GOENV=off GOFLAGS= CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
go build -mod=readonly -buildvcs=false -trimpath \
|
||||
-tags=proxyctl_process_test -o "$work/known-contaminated" ./cmd/proxyctl
|
||||
)
|
||||
if assert_no_process_test_seam "$work/known-contaminated"; then
|
||||
echo 'release artifact validation accepted a known contaminated binary' >&2
|
||||
exit 1
|
||||
fi
|
||||
printf 'process-test seam scan rejected a known contaminated binary\n'
|
||||
|
||||
(
|
||||
cd "$work/first"
|
||||
sha256sum -c SHA256SUMS
|
||||
|
||||
@@ -10,19 +10,31 @@ state="$work/state"
|
||||
bin="$work/bin"
|
||||
mkdir -p "$home" "$config" "$state" "$bin"
|
||||
|
||||
snapshot_host_path() {
|
||||
path=$1
|
||||
if [ ! -e "$path" ] && [ ! -L "$path" ]; then
|
||||
printf 'absent\t%s\n' "$path"
|
||||
return
|
||||
fi
|
||||
|
||||
# Avoid pipelines: traversal, stat, hash, and sort failures must stop the
|
||||
# verification rather than being mistaken for an unchanged host snapshot.
|
||||
find -H "$path" -xdev \
|
||||
-exec stat --printf='metadata\t%F\t%a\t%u\t%g\t%N\n' -- {} + \
|
||||
>"$work/host-snapshot-metadata"
|
||||
LC_ALL=C sort "$work/host-snapshot-metadata"
|
||||
find -H "$path" -xdev -type f -exec sha256sum -- {} + \
|
||||
>"$work/host-snapshot-content"
|
||||
LC_ALL=C sort "$work/host-snapshot-content"
|
||||
}
|
||||
|
||||
snapshot_host() {
|
||||
for path in \
|
||||
"$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.docker/config.json" \
|
||||
/etc/apt/apt.conf.d/99proxyctl /etc/docker/daemon.json \
|
||||
/var/lib/proxyctl/docker-daemon.json
|
||||
/etc/apt/apt.conf.d /etc/docker/daemon.json /var/lib/proxyctl \
|
||||
/etc/systemd/system/docker.service.d
|
||||
do
|
||||
if [ -r "$path" ]; then
|
||||
sha256sum "$path"
|
||||
elif [ -e "$path" ]; then
|
||||
ls -ld "$path"
|
||||
else
|
||||
printf 'absent %s\n' "$path"
|
||||
fi
|
||||
snapshot_host_path "$path"
|
||||
done
|
||||
if command -v gsettings >/dev/null 2>&1; then
|
||||
gsettings get org.gnome.system.proxy mode 2>&1 || true
|
||||
|
||||
Reference in New Issue
Block a user