diff --git a/.github/scripts/verify-manifest.sh b/.github/scripts/verify-manifest.sh new file mode 100755 index 000000000..1bcc5cad0 --- /dev/null +++ b/.github/scripts/verify-manifest.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# +# Fails unless the manifest covers every artifact a release is expected to carry, so a release whose +# matrix arm failed is not signed short. The counts follow the package workflow's matrix: change one, +# change the other. +set -euo pipefail + +manifest="${1:?usage: verify-manifest.sh SHA256SUMS}" + +if [ ! -r "$manifest" ]; then + echo "no readable manifest at ${manifest}" >&2 + exit 1 +fi + +required=( + '\.dmg$:2' # macos, x64 and arm64 + '\.exe$:2' # windows, x64 and arm64 + '\.deb$:1' # linux x64 + '\.rpm$:1' # linux x64 + '\.AppImage$:2' # linux, x64 and arm64 +) + +short=0 +for spec in "${required[@]}"; do + pattern="${spec%:*}" + expected="${spec##*:}" + actual=$(grep -cE "$pattern" "$manifest") || [ $? -eq 1 ] || exit 1 + if [ "$actual" -ne "$expected" ]; then + echo "manifest carries $actual file(s) matching ${pattern}, expected ${expected}" >&2 + short=1 + fi +done + +total=$(wc -l < "$manifest") +if [ "$total" -ne 8 ]; then + echo "manifest carries $total files, expected 8" >&2 + short=1 +fi + +exit "$short" diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 0da88f3fa..fd47fa9f2 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -73,3 +73,27 @@ jobs: gh release upload "v${VERSION}" "${FILES[@]}" --clobber fi + checksums: + name: Publish SHA256SUMS + needs: package + # runs where a matrix arm failed too, and the manifest check below refuses a short set + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: generate and upload SHA256SUMS + shell: bash + env: + GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }} + run: | + set -euo pipefail + VERSION=$(node -p "require('./package.json').version") + mkdir assets + gh release download "v${VERSION}" --dir assets \ + -p '*.dmg' -p '*.exe' -p '*.deb' -p '*.rpm' -p '*.AppImage' + ( cd assets && sha256sum * ) | LC_ALL=C sort -k 2 > SHA256SUMS + cat SHA256SUMS + ./.github/scripts/verify-manifest.sh SHA256SUMS + gh release upload "v${VERSION}" SHA256SUMS --clobber diff --git a/README.md b/README.md index c602faacc..11878eb4b 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,27 @@ This is an unofficial fork of [Polar](https://github.com/jamaljsr/polar) that fo ## Releases -Published under [Releases](https://github.com/privkeyio/polar/releases) with a signed shasums file covering every artifact: +Published under [Releases](https://github.com/privkeyio/polar/releases) with a signed `SHA256SUMS` covering every file: ```bash -gpg --verify polar-*-shasums.txt.asc polar-*-shasums.txt -sha256sum -c polar-*-shasums.txt --ignore-missing +gpg --import privkeyio-signing-key.asc +gpg --verify SHA256SUMS.asc SHA256SUMS +sha256sum --ignore-missing -c SHA256SUMS ``` -The signing key is `A47D 99B6 DB0D 715D 40C5 9A20 23AE 8A8E A7E2 4E38`. +Signed by Kyle Santiago , key `A47D99B6DB0D715D40C59A2023AE8A8EA7E24E38`. + +The macOS builds are not notarized and the Windows installers are not Authenticode signed, so both are reported as untrusted on first launch. Verify `SHA256SUMS` first, because clearing quarantine removes the check that would otherwise stop a tampered download: + +```bash +xattr -dr com.apple.quarantine "/Applications/Polar BLAKE2b.app" +``` + +The node images are built by the `Images` workflow from the Dockerfiles in [docker](docker), each pinned to a signed checksum file or, for LND, a source commit, as listed in [docker/README.md](docker/README.md). + +## Reporting issues + +Use the [Issues](https://github.com/privkeyio/polar/issues) tab for problems specific to this fork. Anything else belongs [upstream](https://github.com/jamaljsr/polar/issues). ---