mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-14 08:20:11 +00:00
Validate signed release sidecar assets
This commit is contained in:
parent
a442eb6bda
commit
21dde76c6f
3 changed files with 109 additions and 4 deletions
|
|
@ -95,6 +95,64 @@ func TestCreateReleaseUploadsPowerShellInstaller(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReleaseValidationRequiresSignedSidecars(t *testing.T) {
|
||||
localValidatorBytes, err := os.ReadFile(repoFile("scripts", "validate-release.sh"))
|
||||
if err != nil {
|
||||
t.Fatalf("read validate-release.sh: %v", err)
|
||||
}
|
||||
localValidator := string(localValidatorBytes)
|
||||
localRequired := []string{
|
||||
`info "Validating SSH signature sidecars..."`,
|
||||
`if [ ! -s "checksums.txt.sshsig" ]; then`,
|
||||
`error "Missing or empty checksums.txt.sshsig"`,
|
||||
`if [ ! -s "${filename}.sshsig" ]; then`,
|
||||
`error "Missing or empty ${filename}.sshsig"`,
|
||||
`success "SSH signature sidecars validated"`,
|
||||
}
|
||||
for _, needle := range localRequired {
|
||||
if !strings.Contains(localValidator, needle) {
|
||||
t.Fatalf("validate-release.sh missing signed sidecar validation: %s", needle)
|
||||
}
|
||||
}
|
||||
|
||||
publishedValidatorBytes, err := os.ReadFile(repoFile("scripts", "validate-published-release.sh"))
|
||||
if err != nil {
|
||||
t.Fatalf("read validate-published-release.sh: %v", err)
|
||||
}
|
||||
publishedValidator := string(publishedValidatorBytes)
|
||||
publishedRequired := []string{
|
||||
`CHECKSUMS_SIG_PATH="${TMP_DIR}/checksums.txt.sshsig"`,
|
||||
`"${BASE_URL}/checksums.txt.sshsig"`,
|
||||
`echo "Failed to download checksums.txt.sshsig for ${TAG}" >&2`,
|
||||
`sshsig_path="${TMP_DIR}/${filename}.sshsig"`,
|
||||
`"${artifact_url}.sshsig"`,
|
||||
`echo "Failed to download ${filename}.sshsig" >&2`,
|
||||
`Published release assets for ${TAG} match checksums.txt, *.sha256 files, and required *.sshsig sidecars.`,
|
||||
}
|
||||
for _, needle := range publishedRequired {
|
||||
if !strings.Contains(publishedValidator, needle) {
|
||||
t.Fatalf("validate-published-release.sh missing signed sidecar validation: %s", needle)
|
||||
}
|
||||
}
|
||||
|
||||
contractBytes, err := os.ReadFile(repoFile("docs", "release-control", "v6", "internal", "subsystems", "deployment-installability.md"))
|
||||
if err != nil {
|
||||
t.Fatalf("read deployment-installability contract: %v", err)
|
||||
}
|
||||
contract := string(contractBytes)
|
||||
contractRequired := []string{
|
||||
"`scripts/validate-release.sh`, and",
|
||||
"`scripts/validate-published-release.sh` must derive the embedded update trust",
|
||||
"fail validation if any",
|
||||
"published artifact or `checksums.txt` is missing its `.sshsig` sidecar",
|
||||
}
|
||||
for _, needle := range contractRequired {
|
||||
if !strings.Contains(contract, needle) {
|
||||
t.Fatalf("deployment-installability contract missing signed sidecar validation requirement: %s", needle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerAndDemoBuildsUseCanonicalReleaseLdflags(t *testing.T) {
|
||||
dockerfileBytes, err := os.ReadFile(repoFile("Dockerfile"))
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
# Remote release validator.
|
||||
# Downloads the published (or draft) assets straight from GitHub Releases,
|
||||
# recalculates their SHA256 sums, and ensures checksums.txt and the *.sha256
|
||||
# helper files match what is actually live. This prevents broken updates when
|
||||
# artifacts are re-uploaded without regenerating checksums (see issue #698).
|
||||
# recalculates their SHA256 sums, and ensures checksums.txt, the *.sha256
|
||||
# helper files, and the required *.sshsig sidecars match the live release
|
||||
# packet. This prevents broken updates when artifacts are re-uploaded without
|
||||
# regenerating checksums or their pinned signature sidecars (see issue #698).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
|
|
@ -29,6 +30,17 @@ if ! "${curl_args[@]}" "${BASE_URL}/checksums.txt" >"$CHECKSUMS_PATH"; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
CHECKSUMS_SIG_PATH="${TMP_DIR}/checksums.txt.sshsig"
|
||||
echo "Downloading ${BASE_URL}/checksums.txt.sshsig"
|
||||
if ! "${curl_args[@]}" "${BASE_URL}/checksums.txt.sshsig" >"$CHECKSUMS_SIG_PATH"; then
|
||||
echo "Failed to download checksums.txt.sshsig for ${TAG}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -s "$CHECKSUMS_SIG_PATH" ]]; then
|
||||
echo "checksums.txt.sshsig is empty for ${TAG}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
status=0
|
||||
|
||||
while read -r checksum filename _; do
|
||||
|
|
@ -66,6 +78,17 @@ while read -r checksum filename _; do
|
|||
echo "${filename}.sha256 content mismatch (expected '${expected_line}', got '${sha_content}')" >&2
|
||||
status=$((status + 1))
|
||||
fi
|
||||
|
||||
sshsig_path="${TMP_DIR}/${filename}.sshsig"
|
||||
if ! "${curl_args[@]}" "${artifact_url}.sshsig" >"$sshsig_path"; then
|
||||
echo "Failed to download ${filename}.sshsig" >&2
|
||||
status=$((status + 1))
|
||||
continue
|
||||
fi
|
||||
if [[ ! -s "$sshsig_path" ]]; then
|
||||
echo "${filename}.sshsig is empty" >&2
|
||||
status=$((status + 1))
|
||||
fi
|
||||
done < "$CHECKSUMS_PATH"
|
||||
|
||||
if [[ "$status" -ne 0 ]]; then
|
||||
|
|
@ -73,4 +96,4 @@ if [[ "$status" -ne 0 ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
echo "Published release assets for ${TAG} match checksums.txt and *.sha256 files."
|
||||
echo "Published release assets for ${TAG} match checksums.txt, *.sha256 files, and required *.sshsig sidecars."
|
||||
|
|
|
|||
|
|
@ -364,12 +364,36 @@ info "Validating checksums..."
|
|||
sha256sum -c checksums.txt >/dev/null 2>&1 || { error "checksums.txt validation failed"; exit 1; }
|
||||
success "checksums.txt validated"
|
||||
|
||||
# Validate release signature sidecars
|
||||
info "Validating SSH signature sidecars..."
|
||||
if [ ! -s "checksums.txt.sshsig" ]; then
|
||||
error "Missing or empty checksums.txt.sshsig"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS= read -r line; do
|
||||
checksum=$(echo "$line" | awk '{print $1}')
|
||||
filename=$(echo "$line" | awk '{print $2}')
|
||||
|
||||
[ -n "$checksum" ] || continue
|
||||
[ -n "$filename" ] || continue
|
||||
|
||||
if [ ! -s "${filename}.sshsig" ]; then
|
||||
error "Missing or empty ${filename}.sshsig"
|
||||
exit 1
|
||||
fi
|
||||
done < checksums.txt
|
||||
success "SSH signature sidecars validated"
|
||||
|
||||
# Validate individual .sha256 files exist and match checksums.txt
|
||||
info "Validating individual .sha256 files..."
|
||||
while IFS= read -r line; do
|
||||
checksum=$(echo "$line" | awk '{print $1}')
|
||||
filename=$(echo "$line" | awk '{print $2}')
|
||||
|
||||
[ -n "$checksum" ] || continue
|
||||
[ -n "$filename" ] || continue
|
||||
|
||||
# Check .sha256 file exists
|
||||
if [ ! -f "${filename}.sha256" ]; then
|
||||
error "Missing ${filename}.sha256"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue