80 lines
4.2 KiB
Bash
80 lines
4.2 KiB
Bash
#!/bin/sh
|
|
# Exact staged executable, real receive-pack, private synthetic tmpfs inputs.
|
|
set +vx
|
|
set -eu
|
|
PATH=/usr/bin:/bin
|
|
export PATH
|
|
version=$1 dispatcher=$2
|
|
test "$(id -u)" = 1000
|
|
test "$(stat -f -c %t /dev/shm)" = 1021994
|
|
umask 077
|
|
base=$(mktemp -d /dev/shm/forge-receive-activation-XXXXXXXX)
|
|
printf '%s' receive-batch-probe > "$base/.owner"
|
|
phase=setup
|
|
cleanup() {
|
|
code=$?
|
|
trap - EXIT HUP INT TERM
|
|
if test "$code" != 0; then printf '{"probe_phase":"%s","exit_code":%s,"result":"unverified"}\n' "$phase" "$code" >&2; fi
|
|
if test -d "$base" && test ! -L "$base" && test "$(cat "$base/.owner")" = receive-batch-probe; then
|
|
rm -rf -- "$base" || code=41
|
|
else code=41; fi
|
|
exit "$code"
|
|
}
|
|
trap cleanup EXIT
|
|
trap 'exit 42' HUP INT TERM
|
|
export HOME="$base" TMPDIR="$base" GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null GIT_TERMINAL_PROMPT=0
|
|
mkdir -p "$base/template/hooks/pre-receive.d"
|
|
hook="$base/template/hooks/pre-receive.d/10-custodian-secret-scan"
|
|
printf '#!/bin/sh\nset +vx\nset -eu\nexec %s/receive-secret-scan --scanner %s/gitleaks\n' "$version" "$version" > "$hook"
|
|
chmod 755 "$hook"
|
|
git -c init.templateDir="$base/template" init -q --bare "$base/server.git"
|
|
cp "$dispatcher" "$base/server.git/hooks/pre-receive"
|
|
chmod 755 "$base/server.git/hooks/pre-receive"
|
|
git init -q -b main "$base/client"
|
|
git -C "$base/client" config core.hooksPath "$base/no-hooks"
|
|
git -C "$base/client" config user.name 'Custodian isolated receive probe'
|
|
git -C "$base/client" config user.email 'probe@example.test'
|
|
printf 'clean baseline\n' > "$base/client/source.txt"
|
|
printf '{"values/secrets-engine.yaml": "%s"}\n' "$(printf synthetic-public-digest | sha256sum | cut -d ' ' -f 1)" > "$base/client/source-pin.json"
|
|
git -C "$base/client" add source.txt source-pin.json
|
|
git -C "$base/client" commit -qm 'isolated clean baseline'
|
|
phase=clean_push
|
|
git -C "$base/client" push "$base/server.git" HEAD:refs/heads/main > "$base/clean.out" 2>&1
|
|
grep -q '"status":"clean"' "$base/clean.out"
|
|
initial=$(git -C "$base/client" rev-parse HEAD)
|
|
phase=synthetic_key
|
|
ssh-keygen -q -t ed25519 -N '' -f "$base/synthetic-key" >/dev/null 2>&1
|
|
cp "$base/synthetic-key" "$base/client/fixture.txt"
|
|
git -C "$base/client" add fixture.txt
|
|
git -C "$base/client" commit -qm 'isolated synthetic fixture'
|
|
rejected=$(git -C "$base/client" rev-parse HEAD)
|
|
git -C "$base/client" rm -q fixture.txt
|
|
git -C "$base/client" commit -qm 'remove fixture from tip'
|
|
phase=blocked_history
|
|
if git -C "$base/client" push "$base/server.git" HEAD:refs/heads/main > "$base/blocked.out" 2>&1; then exit 43; fi
|
|
grep -q '"status":"blocked"' "$base/blocked.out"
|
|
if grep -q 'BEGIN OPENSSH PRIVATE KEY' "$base/blocked.out"; then exit 44; fi
|
|
if git -C "$base/server.git" cat-file -e "$rejected" >/dev/null 2>&1; then exit 45; fi
|
|
test "$(git -C "$base/server.git" rev-parse refs/heads/main)" = "$initial"
|
|
git -C "$base/client" checkout -qb recovery "$initial"
|
|
printf 'clean recovery\n' > "$base/client/source.txt"
|
|
git -C "$base/client" add source.txt
|
|
git -C "$base/client" commit -qm 'isolated clean recovery'
|
|
phase=unavailable_scanner
|
|
recovery=$(git -C "$base/client" rev-parse HEAD)
|
|
cp "$hook" "$base/saved-hook"
|
|
printf '#!/bin/sh\nexec %s/receive-secret-scan --scanner /nonexistent\n' "$version" > "$base/server.git/hooks/pre-receive.d/10-custodian-secret-scan"
|
|
if git -C "$base/client" push "$base/server.git" HEAD:refs/heads/main > "$base/unavailable.out" 2>&1; then exit 46; fi
|
|
grep -q '"status":"unverified"' "$base/unavailable.out"
|
|
test "$(git -C "$base/server.git" rev-parse refs/heads/main)" = "$initial"
|
|
if git -C "$base/server.git" cat-file -e "$recovery" >/dev/null 2>&1; then exit 47; fi
|
|
cp "$base/saved-hook" "$base/server.git/hooks/pre-receive.d/10-custodian-secret-scan"
|
|
phase=clean_recovery
|
|
git -C "$base/client" push "$base/server.git" HEAD:refs/heads/main > "$base/recovered.out" 2>&1
|
|
grep -q '"status":"clean"' "$base/recovered.out"
|
|
test "$(git -C "$base/server.git" rev-parse refs/heads/main)" = "$recovery"
|
|
trap - EXIT HUP INT TERM
|
|
test "$(cat "$base/.owner")" = receive-batch-probe
|
|
rm -rf -- "$base"
|
|
test ! -e "$base"
|
|
printf '{"json_digest_clean_push":true,"intermediate_secret_refused":true,"quarantine_discarded":true,"scanner_unavailable_refused":true,"clean_recovery":true,"temporary_probe_removed":true,"builtin_authorization_excluded":true}\n'
|