1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env bash
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
versions="$root/internal/versions/versions.json"
usage() {
cat >&2 <<EOF
usage: $0 --out DIR
Builds the pinned downloads a bidder's GuestControlPlane serves at /v1/downloads/<sha256>/<name>
(the socialweb-guest-downloads asset of internal/versions/versions.json) into DIR:
opentunnel-x86_64, opentunnel-aarch64 the assets.opentunnel release tarballs, sha256 verified
wootty-x86_64, wootty-aarch64 the guestDownloads.files.wootty image layers, sha256 verified
atirc-x86_64 the guestDownloads.files.atirc binary, sha256 verified (linux/amd64 only)
socialweb-guest-agent-x86_64, socialweb-guest-agent-aarch64 cmd/socialweb-guest-agent (linux, CGO disabled)
each with a sha256sum-format <name>.sha256 sidecar. The tarballs and layers are kept in
\$GUEST_DOWNLOADS_CACHE by their sha256 when it is set.
EOF
exit 2
}
out=""
while [ $# -gt 0 ]; do
case "$1" in
--out) out="$2"; shift 2 ;;
-h|--help) usage ;;
*) usage ;;
esac
done
[ -n "$out" ] || usage
case "$out" in
/tmp|/tmp/*) echo "build-guest-downloads: --out $out is under /tmp" >&2; exit 1 ;;
esac
for tool in curl jq tar sha256sum go; do
command -v "$tool" >/dev/null 2>&1 || { echo "build-guest-downloads: $tool is required" >&2; exit 1; }
done
mkdir -p "$out"
out="$(cd "$out" && pwd -P)"
work="$(mktemp -d "$out/.work.XXXXXX")"
trap 'rm -rf "$work"' EXIT
cache="${GUEST_DOWNLOADS_CACHE:-$work/cache}"
mkdir -p "$cache"
sha_of() { sha256sum "$1" | cut -d' ' -f1; }
fetch_pinned() {
local url="$1" want="$2" auth="${3:-}" file="$cache/$2" part
local args=()
if [ -f "$file" ] && [ "$(sha_of "$file")" = "$want" ]; then
echo "$file"
return
fi
part="$file.part.$BASHPID"
[ -z "$auth" ] || args=(-H "Authorization: Bearer $auth")
curl "${args[@]}" -fSL --retry 5 --retry-all-errors --retry-delay 3 --connect-timeout 10 --speed-limit 10000 --speed-time 20 -s -o "$part" "$url" \
|| { rm -f "$part"; echo "build-guest-downloads: download failed: $url" >&2; exit 1; }
if [ "$(sha_of "$part")" != "$want" ]; then
echo "build-guest-downloads: $url has sha256 $(sha_of "$part"), pinned $want" >&2
rm -f "$part"
exit 1
fi
mv -f "$part" "$file"
echo "$file"
}
registry_token() {
local registry="$1" repository="$2" token
token="$(curl -fsS --retry 5 --retry-all-errors --retry-delay 3 --connect-timeout 10 "https://$registry/token?scope=repository:$repository:pull" | jq -r '.token // empty')" \
|| { echo "build-guest-downloads: no pull token from $registry for $repository" >&2; exit 1; }
[ -n "$token" ] || { echo "build-guest-downloads: $registry gave an empty pull token for $repository" >&2; exit 1; }
echo "$token"
}
extract_member() {
local name="$1" archive="$2" member="$3"
mkdir -p "$work/$name"
tar -xzf "$archive" -C "$work/$name" -- "$member"
local src="$work/$name/$member"
if [ -L "$src" ] || [ ! -f "$src" ]; then
echo "build-guest-downloads: $member in $archive is not a regular file" >&2
exit 1
fi
cp "$src" "$out/$name"
chmod 0755 "$out/$name"
(cd "$out" && sha256sum "$name" >"$name.sha256")
}
for pair in x86_64:amd64 aarch64:arm64; do
arch="${pair%%:*}"
goarch="${pair##*:}"
pin="$(jq -c --arg p "linux/$goarch" '.assets.opentunnel.fetch[$p]' "$versions")"
[ "$pin" != null ] || { echo "build-guest-downloads: assets.opentunnel pins nothing for linux/$goarch" >&2; exit 1; }
[ "$(echo "$pin" | jq -r .archive)" = tar.gz ] || { echo "build-guest-downloads: the opentunnel linux/$goarch pin is not a tar.gz" >&2; exit 1; }
member="$(echo "$pin" | jq -r '.members | keys[0]')"
tarball="$(fetch_pinned "$(echo "$pin" | jq -r .url)" "$(echo "$pin" | jq -r .sha256)")"
echo "build-guest-downloads: opentunnel-$arch from $(basename "$(echo "$pin" | jq -r .url)") member $member" >&2
extract_member "opentunnel-$arch" "$tarball" "$member"
pin="$(jq -c --arg p "linux/$goarch" '.guestDownloads.files.wootty.fetch[$p]' "$versions")"
[ "$pin" != null ] || { echo "build-guest-downloads: guestDownloads.files.wootty pins nothing for linux/$goarch" >&2; exit 1; }
[ "$(echo "$pin" | jq -r .kind)" = oci-layer ] || { echo "build-guest-downloads: the wootty linux/$goarch pin is not an oci-layer" >&2; exit 1; }
registry="$(echo "$pin" | jq -r .registry)"
repository="$(echo "$pin" | jq -r .repository)"
sum="$(echo "$pin" | jq -r .sha256)"
member="$(echo "$pin" | jq -r .member)"
layer="$cache/$sum"
if [ ! -f "$layer" ] || [ "$(sha_of "$layer")" != "$sum" ]; then
layer="$(fetch_pinned "https://$registry/v2/$repository/blobs/sha256:$sum" "$sum" "$(registry_token "$registry" "$repository")")"
fi
echo "build-guest-downloads: wootty-$arch from $registry/$repository layer sha256:$sum member $member" >&2
extract_member "wootty-$arch" "$layer" "$member"
pin="$(jq -c --arg p "linux/$goarch" '.guestDownloads.files.atirc.fetch[$p]' "$versions")"
if [ "$pin" = null ]; then
[ "$goarch" != amd64 ] || { echo "build-guest-downloads: guestDownloads.files.atirc pins nothing for linux/amd64" >&2; exit 1; }
echo "build-guest-downloads: no atirc-$arch: guestDownloads.files.atirc pins nothing for linux/$goarch (atirc is linux/amd64 only)" >&2
else
[ "$(echo "$pin" | jq -r .kind)" = binary ] || { echo "build-guest-downloads: the atirc linux/$goarch pin is not a binary" >&2; exit 1; }
bin="$(fetch_pinned "$(echo "$pin" | jq -r .url)" "$(echo "$pin" | jq -r .sha256)")"
echo "build-guest-downloads: atirc-$arch from $(echo "$pin" | jq -r .url)" >&2
cp "$bin" "$out/atirc-$arch"
chmod 0755 "$out/atirc-$arch"
(cd "$out" && sha256sum "atirc-$arch" >"atirc-$arch.sha256")
fi
echo "build-guest-downloads: building socialweb-guest-agent-$arch" >&2
(cd "$root" && CGO_ENABLED=0 GOOS=linux GOARCH="$goarch" go build -trimpath -buildvcs=false \
-ldflags='-s -w -buildid=' -o "$out/socialweb-guest-agent-$arch" ./cmd/socialweb-guest-agent)
(cd "$out" && sha256sum "socialweb-guest-agent-$arch" >"socialweb-guest-agent-$arch.sha256")
done
(cd "$out" && sha256sum -c --quiet ./*.sha256) || { echo "build-guest-downloads: a download does not match its sidecar" >&2; exit 1; }
for f in "$out"/*.sha256; do
echo "build-guest-downloads: $(cat "$f")" >&2
done