feat: add deployment foundation and cross-device handoff

This commit is contained in:
2026-09-25 08:49:19 +08:00
parent 8ccb8b7c15
commit e965b0943d
77 changed files with 8018 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Local opt-in public deb download/hash test. No extraction, APT or installation.
# Called by probe-docker-repository.sh after authenticated metadata verification.
set -euo pipefail
[[ $# == 3 && -f "$1" && -d "$2" ]]
binary=$1
metadata_dir=$2
metadata_request=$3
probe_dir=$(mktemp -d /tmp/server-deploy-artifacts.XXXXXX)
chmod 700 "$probe_dir"
artifact_dir="$probe_dir/debs"
mkdir -m 700 "$artifact_dir"
# Only authenticated lock paths, fixed origin, no caller-provided download URLs.
python3 -I -c 'import json,re,sys; r=json.load(sys.stdin); assert r["repositoryAuthenticated"] is True; p=r["lock"]["packages"]; assert len(p)==5; [None if re.fullmatch(r"dists/resolute/pool/stable/amd64/[a-z0-9.+~_-]+\.deb",x["filename"]) and 0<x["size"]<=536870912 else sys.exit(1) for x in p]; [print(x["filename"],x["size"]) for x in p]' < "$metadata_dir/result.json" > "$probe_dir/downloads"
while read -r filename size; do
curl --fail --silent --show-error --proto '=https' --max-time 90 --max-filesize "$size" \
"https://download.docker.com/linux/ubuntu/$filename" -o "$artifact_dir/${filename##*/}"
done < "$probe_dir/downloads"
request=$(printf '%s\n' "$metadata_request" | python3 -I -c 'import json,sys; r=json.load(sys.stdin); r["artifactDirectory"]=sys.argv[1]; print(json.dumps(r))' "$artifact_dir")
printf '%s\n' "$request" | "$binary" verify-artifacts > "$probe_dir/result.json"
python3 -I -c 'import json,sys; r=json.load(sys.stdin); assert r["repositoryAuthenticated"] is True; assert r["packageBytesVerified"] is True; assert r["executable"] is False; assert len(r["lock"]["packages"])==5' < "$probe_dir/result.json"
cat "$probe_dir/result.json"
# Same-size mutation: digest comparison, not an earlier size check, must reject.
first=$(head -n 1 "$probe_dir/downloads")
filename=${first% *}
printf 'X' | dd of="$artifact_dir/${filename##*/}" bs=1 count=1 conv=notrunc status=none
if printf '%s\n' "$request" | "$binary" verify-artifacts > "$probe_dir/rejected.json"; then
printf 'ERROR: same-size deb tamper accepted\n' >&2
exit 1
fi
[[ ! -s "$probe_dir/rejected.json" ]]
printf 'Five real deb files verified; same-size tamper rejected. Local artifacts: %s\n' "$artifact_dir"
+55
View File
@@ -0,0 +1,55 @@
#!/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"
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Run on Linux/WSL with a previously SHA-256-verified official Go tarball.
# The caller owns download provenance. No package installation or production SSH.
set -euo pipefail
if [[ $# != 1 || ! -f "$1" ]]; then
printf 'usage: bash scripts/verify-linux.sh /path/to/verified-go.linux-amd64.tar.gz\n' >&2
exit 2
fi
task_dir=$(mktemp -d /tmp/server-deploy-test.XXXXXX)
tar -xzf "$1" -C "$task_dir"
export GOCACHE="$task_dir/cache"
cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.."
"$task_dir/go/bin/go" test ./... -count=1 -v -timeout=60s
"$task_dir/go/bin/go" vet ./...
"$task_dir/go/bin/go" test -race ./... -count=1 -timeout=60s
"$task_dir/go/bin/go" build -o "$task_dir/deployctl" ./cmd/deployctl
"$task_dir/deployctl" plan < protocol/examples/plan-request.json
"$task_dir/deployctl" inspect
"$task_dir/deployctl" preflight
if [[ "${DEPLOYCTL_ONLINE_REPOSITORY_PROBE:-0}" == 1 ]]; then
DEPLOYCTL_TEST_GO="$task_dir/go/bin/go" bash scripts/probe-docker-repository.sh "$task_dir/deployctl"
fi
printf 'Verification artifacts retained at: %s\n' "$task_dir"