diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 104df6ae7..0fe0f42dd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -7,6 +7,10 @@ jobs: publish_release: name: Release runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + packages: write steps: - name: Checkout head uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -32,6 +36,8 @@ jobs: uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version-file: 'go.mod' + - name: Set up cosign + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 - name: Get tag version id: git run: echo "tag_version=$(make version)" >> "$GITHUB_OUTPUT" diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2c13ec2ab..ea73d100c 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -45,6 +45,19 @@ archives: checksum: name_template: 'checksums.txt' +signs: + - certificate: ${artifact}-keyless.pem + signature: ${artifact}-keyless.sig + cmd: cosign + args: + - sign-blob + - --b64=false + - --output-certificate=${certificate} + - --output-signature=${signature} + - --yes + - ${artifact} + artifacts: checksum + snapshot: name_template: "{{ .Tag }}-next" @@ -172,6 +185,13 @@ dockers: - "--label=org.opencontainers.image.version={{.Version}}" - "--label=org.opencontainers.image.source=https://github.com/UpCloudLtd/upcloud-cli.git" +docker_signs: + - args: + - sign + - --yes + - ${artifact}@${digest} + artifacts: all + release: # Repo in which the release will be created. # Default is extracted from the origin remote URL or empty if its private hosted. diff --git a/RELEASING.md b/RELEASING.md index 6ecf339df..ac65aa84b 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -8,6 +8,6 @@ - sets the version based on the tag - creates a draft release to GitHub - populates the release notes from `CHANGELOG.md` with `make release-notes` - - builds and uploads binaries & SHA sum for given release + - builds, uploads, and signs assets for given release 5. Verify that [release notes](https://github.com/UpCloudLtd/upcloud-cli/releases) are in line with `CHANGELOG.MD` 6. Publish the drafted release diff --git a/docs/index.md b/docs/index.md index a1ff1865a..59cbc48df 100644 --- a/docs/index.md +++ b/docs/index.md @@ -86,6 +86,45 @@ After installing `upctl`, you can run `upctl version` command to verify that the upctl version ``` +### Verify assets + +Project release packages' SHA-256 checksums are available in the project releases, +files `checksums.txt`. They can be checked for example with: + +```sh +# make sure at least one downloaded package and checksums.txt are in the current directory +sha256sum -c --ignore-missing checksums.txt +``` + +Project release checksum files and Docker images are signed using the +[Sigstore framework](https://www.sigstore.dev), and can be verified with +[cosign](https://docs.sigstore.dev/cosign/). + +For example, to verify package checksums file for a release: + +```sh +project_url=https://github.com/UpCloudLtd/upcloud-cli +release=vX.Y.Z +cosign verify-blob \ + --certificate-identity ${project_url}/.github/workflows/publish.yml@refs/tags/${release} \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + --certificate ${project_url}/releases/download/${release}/checksums.txt-keyless.pem \ + --signature ${project_url}/releases/download/${release}/checksums.txt-keyless.sig \ + ${project_url}/releases/download/${release}/checksums.txt +``` + +And to verify the Docker image for a release: + +```sh +project=UpCloudLtd/upcloud-cli +release=vX.Y.Z +cosign verify \ + ghcr.io/${project}:${release} \ + --certificate-identity https://github.com/${project}/.github/workflows/publish.yml@refs/tags/${release} \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com | + jq . +``` + ### Configure shell completions `upctl` provides shell completions for multiple shells. Run `upctl completion --help` to list the supported shells.