Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -634,33 +634,35 @@ jobs:

SIGNED_COUNT=0

# Find all SBOM files generated by GoReleaser (syft)
# All files are in dist root (MSI files flattened by previous step)
for sbom in "${CALLER_DIST}"/*.sbom.json; do
[ -f "$sbom" ] || continue

SBOM_BASENAME=$(basename "$sbom")
ARCHIVE_NAME="${SBOM_BASENAME%.sbom.json}"
ARCHIVE="${CALLER_DIST}/${ARCHIVE_NAME}"
# Require every Windows release artifact to have an SPDX SBOM.
# MSI files are flattened to dist root by the previous step.
for artifact in "${CALLER_DIST}"/*.zip "${CALLER_DIST}"/*.msi; do
[ -f "$artifact" ] || continue
[[ "$artifact" == *checksums* ]] && continue

if [ ! -f "$ARCHIVE" ]; then
echo "::error::Could not find archive for SBOM: $sbom (expected: $ARCHIVE)"
SBOM="${artifact}.sbom.json"
if [ ! -f "$SBOM" ]; then
echo "::error::Missing SBOM for artifact: $(basename "$artifact") (expected: $SBOM)"
exit 1
fi

echo "Signing SBOM for: $(basename "$ARCHIVE")"
echo "Signing SBOM for: $(basename "$artifact")"
cosign attest-blob \
--yes \
--predicate "$sbom" \
--predicate "$SBOM" \
--type https://spdx.dev/Document \
--bundle "${ARCHIVE}.sbom.sigstore.json" \
"$ARCHIVE" > /dev/null
echo "✅ Created $(basename "$ARCHIVE").sbom.sigstore.json"
--bundle "${artifact}.sbom.sigstore.json" \
"$artifact" > /dev/null
echo "✅ Created $(basename "$artifact").sbom.sigstore.json"
((SIGNED_COUNT++)) || true
done

echo "Generated SBOM bundles: ${SIGNED_COUNT}"
ls "${CALLER_DIST}"/*.sbom.sigstore.json 2>/dev/null || echo "ℹ️ No SBOM bundles generated (GoReleaser may not have generated SBOMs)"
if [ "$SIGNED_COUNT" -eq 0 ]; then
echo "::error::No Windows SBOM bundles were generated - this indicates a build problem"
exit 1
fi
ls "${CALLER_DIST}"/*.sbom.sigstore.json

- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v5
Expand Down
68 changes: 30 additions & 38 deletions scripts/validate-release-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,53 +123,45 @@ for platform in $(echo "$MANIFEST" | jq -r '.assets | keys[]'); do
continue
fi

# Check binary signature (.sig + .cert files) - skip for MSI (derived artifact)
if [[ "$platform" == *-msi ]]; then
info "Skipping .sig/.cert check for $platform (derived artifact)"
else
SIG_FILE="${HREF}.sig"
CERT_FILE="${HREF}.cert"
if curl -sfL "$SIG_FILE" -o "$TEMP_DIR/${FILENAME}.sig" 2>/dev/null && \
curl -sfL "$CERT_FILE" -o "$TEMP_DIR/${FILENAME}.cert" 2>/dev/null; then
if cosign verify-blob \
--signature "$TEMP_DIR/${FILENAME}.sig" \
--certificate "$TEMP_DIR/${FILENAME}.cert" \
--certificate-oidc-issuer "$CERT_OIDC_ISSUER" \
--certificate-identity-regexp "$CERT_IDENTITY_REGEXP" \
"$TEMP_DIR/$FILENAME" > /dev/null 2>&1; then
pass "Binary signature verified: $platform"
else
fail "Binary signature verification failed: $platform"
fi
# Check binary signature (.sig + .cert files)
SIG_FILE="${HREF}.sig"
CERT_FILE="${HREF}.cert"
if curl -sfL "$SIG_FILE" -o "$TEMP_DIR/${FILENAME}.sig" 2>/dev/null && \
curl -sfL "$CERT_FILE" -o "$TEMP_DIR/${FILENAME}.cert" 2>/dev/null; then
if cosign verify-blob \
--signature "$TEMP_DIR/${FILENAME}.sig" \
--certificate "$TEMP_DIR/${FILENAME}.cert" \
--certificate-oidc-issuer "$CERT_OIDC_ISSUER" \
--certificate-identity-regexp "$CERT_IDENTITY_REGEXP" \
"$TEMP_DIR/$FILENAME" > /dev/null 2>&1; then
pass "Binary signature verified: $platform"
else
fail "Binary signature files missing: $platform (.sig or .cert)"
fail "Binary signature verification failed: $platform"
fi
else
fail "Binary signature files missing: $platform (.sig or .cert)"
fi

# Check provenance attestation (skip for MSI - it's derived from the same binary as the zip)
if [[ "$platform" == *-msi ]]; then
info "Skipping provenance check for $platform (derived from zip)"
# Check provenance attestation
PROV_BUNDLE="${HREF}.provenance.sigstore.json"
if ! curl -sfL "$PROV_BUNDLE" -o "$TEMP_DIR/${FILENAME}.provenance.sigstore.json" 2>/dev/null; then
fail "Provenance bundle missing: $PROV_BUNDLE"
else
PROV_BUNDLE="${HREF}.provenance.sigstore.json"
if ! curl -sfL "$PROV_BUNDLE" -o "$TEMP_DIR/${FILENAME}.provenance.sigstore.json" 2>/dev/null; then
fail "Provenance bundle missing: $PROV_BUNDLE"
# Verify provenance
if cosign verify-blob-attestation \
--bundle "$TEMP_DIR/${FILENAME}.provenance.sigstore.json" \
--type https://slsa.dev/provenance/v1 \
--certificate-oidc-issuer "$CERT_OIDC_ISSUER" \
--certificate-identity-regexp "$CERT_IDENTITY_REGEXP" \
"$TEMP_DIR/$FILENAME" > /dev/null 2>&1; then
pass "Provenance verified: $platform"
else
# Verify provenance
if cosign verify-blob-attestation \
--bundle "$TEMP_DIR/${FILENAME}.provenance.sigstore.json" \
--type https://slsa.dev/provenance/v1 \
--certificate-oidc-issuer "$CERT_OIDC_ISSUER" \
--certificate-identity-regexp "$CERT_IDENTITY_REGEXP" \
"$TEMP_DIR/$FILENAME" > /dev/null 2>&1; then
pass "Provenance verified: $platform"
else
fail "Provenance verification failed: $platform"
fi
fail "Provenance verification failed: $platform"
fi
fi

# Check SBOM attestation (skip for checksums and MSI - only binary archives have SBOMs)
if [[ "$platform" == "checksums" || "$platform" == *-msi ]]; then
# Check SBOM attestation
if [[ "$platform" == "checksums" ]]; then
info "Skipping SBOM check for $platform (not applicable)"
else
SBOM_BUNDLE="${HREF}.sbom.sigstore.json"
Expand Down