diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 006e62851..791e057ed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,6 +78,9 @@ jobs: release: runs-on: ubuntu-latest needs: build + permissions: + contents: write + id-token: write # required for cosign keyless OIDC signing steps: - name: Download artifacts uses: actions/download-artifact@v8 @@ -85,6 +88,18 @@ jobs: path: dist merge-multiple: true + - name: Generate checksums + working-directory: dist + shell: bash + run: sha256sum lf-*.{zip,tar.gz} > sha256sums.txt + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Sign checksums (sigstore keyless) + working-directory: dist + run: cosign sign-blob --yes --bundle sha256sums.txt.sigstore.json sha256sums.txt + - name: Release uses: softprops/action-gh-release@v2 with: diff --git a/README.md b/README.md index bbd1443ae..91dc409ac 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ See [faq](https://github.com/gokcehan/lf/wiki/FAQ) for more information and [tut See [packages](https://github.com/gokcehan/lf/wiki/Packages) for community maintained packages. See [releases](https://github.com/gokcehan/lf/releases) for pre-built binaries. +See [security](SECURITY.md) for release verification and reproducible builds. Building from the source requires [Go](https://go.dev/). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..a75afb92c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,34 @@ +# Verifying Releases + +Release artifacts are signed using [sigstore cosign](https://github.com/sigstore/cosign) with keyless signing. +Each signing event is recorded in the [Rekor](https://rekor.sigstore.dev) transparency log, providing a public auditable record that the artifacts were built by the official GitHub Actions release workflow. + +A single signature is produced over `sha256sums.txt`, which lists the SHA-256 of every release archive. Verifying the signature on `sha256sums.txt` and then verifying each archive against `sha256sums.txt` gives the same end-to-end guarantee as a per-archive signature. + +## Verify a download + +Install cosign: + + go install github.com/sigstore/cosign/v3/cmd/cosign@latest + +Download `sha256sums.txt`, `sha256sums.txt.sigstore.json`, and the archive(s) you want from the [releases page](https://github.com/gokcehan/lf/releases), then: + + cosign verify-blob sha256sums.txt \ + --bundle sha256sums.txt.sigstore.json \ + --certificate-identity "https://github.com/gokcehan/lf/.github/workflows/release.yml@refs/tags/TAG" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" + +Replace `TAG` with the release tag (e.g. `r33`). + +Once `sha256sums.txt` is trusted, verify the archive(s) against it: + + sha256sum --check --ignore-missing sha256sums.txt + +## Reproduce a build + +Builds are reproducible given the same Go version and source: + + go version -m ./lf # shows the exact Go version used + git checkout TAG + CGO_ENABLED=0 go build -trimpath -ldflags="-s -w -X main.gVersion=TAG" + sha256sum lf # compare with sha256sums.txt