diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 217a195..a348f3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -260,6 +260,36 @@ jobs: fi grep -q -- "--no-verify" "$RUNNER_TEMP/err" + # cosign v2 reads the release's Sigstore bundles from 2.4 on, with a flag the script adds. + - name: Install cosign v2.4 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 + with: + cosign-release: "v2.4.1" + + - name: Install the latest release with the script and cosign v2.4 + run: | + set -eu + cosign version | grep -q 'GitVersion: *v2\.4\.1' + sh install.sh --dir "$RUNNER_TEMP/bin-v2" --no-man + "$RUNNER_TEMP/bin-v2/hodeishield" --version + + # Older cosign versions cannot read them: the script must say which version it needs. + - name: Install cosign v2.2 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 + with: + cosign-release: "v2.2.4" + + - name: The script names the cosign version it needs + run: | + set -eu + cosign version | grep -q 'GitVersion: *v2\.2\.4' + if sh install.sh --dir "$RUNNER_TEMP/bin-old" --no-man 2> "$RUNNER_TEMP/err-old"; then + echo "::error::install.sh accepted cosign v2.2.4" + exit 1 + fi + grep -q "install cosign v3 (or v2.4 or newer)" "$RUNNER_TEMP/err-old" + test ! -e "$RUNNER_TEMP/bin-old/hodeishield" + # The repository freshness monitor must go red: its control builds small repositories with a # throwaway key, serves them from localhost and checks that every stale, altered, unsigned or # missing case fails and the current one passes. diff --git a/CHANGELOG.md b/CHANGELOG.md index dc2746d..03a1581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ commands, `--json` output and exit codes. Each release's notes start with its se ## [Unreleased] +### Fixed + +- `install.sh` now checks the release's signature with cosign v2 (2.4 or newer) as well as v3. With + cosign v2 it stopped with "the Sigstore signature does not verify" although the release was + genuine: the signatures are Sigstore bundles that cosign v2 reads only with `--new-bundle-format`, + which the script now adds. With an older cosign it names the version it needs instead. The README + and `docs/verifying-releases.md` now say which cosign versions work, and what to add with v2. + ([#141](https://github.com/Hodeitek/hodeishield-cli/issues/141)) + ## [0.4.0] - 2026-10-12 ### Added diff --git a/README.md b/README.md index 7c9e9ac..4cad1bb 100644 --- a/README.md +++ b/README.md @@ -154,8 +154,10 @@ less install.sh sh install.sh --version $v ``` -It needs `cosign` to check the archive's signature and stops if it is missing; `--no-verify` skips -that check (the checksum still runs). `sh install.sh --help` lists the options (`--dir`, `--no-man`). +It needs `cosign` v3, or v2.4 or newer, to check the archive's signature, and stops if it is missing +or older; `--no-verify` skips that check (the checksum still runs). To check `install.sh` itself with +cosign v2 as above, add `--new-bundle-format` to `cosign verify-blob`. `sh install.sh --help` lists +the options (`--dir`, `--no-man`). ### Container image diff --git a/docs/verifying-releases.md b/docs/verifying-releases.md index 87e25f0..b4a15bd 100644 --- a/docs/verifying-releases.md +++ b/docs/verifying-releases.md @@ -50,7 +50,9 @@ what the next two steps are for. ## 3. Verify the Sigstore signature -Requires [`cosign`](https://github.com/sigstore/cosign) (v2 or newer). +Requires [`cosign`](https://github.com/sigstore/cosign) v3. With cosign v2 (2.4 or newer), add +`--new-bundle-format` to each `cosign verify-blob` command below: the signatures are Sigstore bundles +in the format cosign v3 reads by default. Older cosign versions cannot read them. ```sh cosign verify-blob \ diff --git a/install.sh b/install.sh index 74fbfba..a0252dc 100755 --- a/install.sh +++ b/install.sh @@ -16,7 +16,8 @@ # --no-verify skip the cosign signature check (the SHA256SUMS check always runs). Only for # machines that cannot run cosign; the checksum alone does not prove who built it. # -# Needs curl, tar and sha256sum or shasum; cosign (https://docs.sigstore.dev) unless --no-verify. +# Needs curl, tar and sha256sum or shasum; cosign v3, or v2.4 or newer (https://docs.sigstore.dev), +# unless --no-verify. set -eu @@ -64,6 +65,17 @@ fi if [ "$verify" -eq 1 ] && ! command -v cosign > /dev/null 2>&1; then die "cosign is required to check the signature: install it (https://docs.sigstore.dev/cosign/system_config/installation/) and run this again. To install without the signature check, pass --no-verify." fi +# The signatures are Sigstore bundles in the format cosign v3 reads by default. cosign v2 reads them +# from 2.4 on when asked to (--new-bundle-format), and older versions cannot read them at all. +bundle_format= +if [ "$verify" -eq 1 ]; then + cosign_version=$(cosign version 2> /dev/null | awk '$1 == "GitVersion:" { print $2; exit }') + case $cosign_version in + v0.* | v1.* | v2.[0-3] | v2.[0-3].*) + die "cosign ${cosign_version} cannot read the release's signatures: install cosign v3 (or v2.4 or newer) and run this again." ;; + v2.*) bundle_format=--new-bundle-format ;; + esac +fi case "$(uname -s)" in Linux) @@ -112,7 +124,7 @@ expected=$(awk -v f="${name}.tar.gz" '$2 == f || $2 == "*" f { print $1 }' "${tm printf 'Checksum: OK\n' if [ "$verify" -eq 1 ]; then - cosign verify-blob \ + cosign verify-blob ${bundle_format:+"$bundle_format"} \ --bundle "${tmp}/${name}.tar.gz.sigstore.json" \ --certificate-identity "${WORKFLOW}@refs/tags/v${version}" \ --certificate-oidc-issuer "$ISSUER" \