From 7fa1be126ea1c894a16685c18604273064277738 Mon Sep 17 00:00:00 2001 From: Radoslav Dimitrov Date: Mon, 30 Oct 2023 16:47:10 +0200 Subject: [PATCH] Add goreleaser, sboms, slsa3, sigstore and homebrew support (#1315) * add goreleaser, sboms, slsa3, sigstore and homebrew support Signed-off-by: Radoslav Dimitrov * fix env vars for ldflags Signed-off-by: Radoslav Dimitrov * use commit date for ldflags Signed-off-by: Radoslav Dimitrov * allow slsa generator to run for private repo Signed-off-by: Radoslav Dimitrov --------- Signed-off-by: Radoslav Dimitrov --- .github/workflows/releaser.yml | 154 +++++++++++++++++++++++++ .github/workflows/slsa-go-releaser.yml | 94 --------------- .goreleaser.yaml | 82 +++++++++++++ .slsa-goreleaser/darwin-amd64.yml | 31 ----- .slsa-goreleaser/darwin-arm64.yml | 31 ----- .slsa-goreleaser/linux-amd64.yml | 31 ----- .slsa-goreleaser/linux-arm64.yml | 31 ----- .slsa-goreleaser/windows-amd64.yml | 31 ----- .slsa-goreleaser/windows-arm64.yml | 32 ----- 9 files changed, 236 insertions(+), 281 deletions(-) create mode 100644 .github/workflows/releaser.yml delete mode 100644 .github/workflows/slsa-go-releaser.yml create mode 100644 .goreleaser.yaml delete mode 100644 .slsa-goreleaser/darwin-amd64.yml delete mode 100644 .slsa-goreleaser/darwin-arm64.yml delete mode 100644 .slsa-goreleaser/linux-amd64.yml delete mode 100644 .slsa-goreleaser/linux-arm64.yml delete mode 100644 .slsa-goreleaser/windows-amd64.yml delete mode 100644 .slsa-goreleaser/windows-arm64.yml diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml new file mode 100644 index 0000000000..eebf6bcd78 --- /dev/null +++ b/.github/workflows/releaser.yml @@ -0,0 +1,154 @@ +# +# Copyright 2023 Stacklok, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This workflow compiles your mediator server and medic using a SLSA3 compliant +# build and then verifies the provenance of the built artifacts. +# It releases the following architectures: amd64, arm64, and armv7 on Linux, +# Windows, and macOS. +# The provenance file can be verified using https://github.com/slsa-framework/slsa-verifier. +# For more information about SLSA and how it improves the supply-chain, visit slsa.dev. + +name: Release +on: + workflow_dispatch: + release: + types: [created] + +permissions: + contents: write + +jobs: + ldflags_args: + runs-on: ubuntu-latest + outputs: + commit-date: ${{ steps.ldflags.outputs.commit-date }} + commit: ${{ steps.ldflags.outputs.commit }} + version: ${{ steps.ldflags.outputs.version }} + tree-state: ${{ steps.ldflags.outputs.tree-state }} + steps: + - id: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - id: ldflags + run: | + echo "::set-output name=commit-date::$(git log --date=iso8601-strict -1 --pretty=%ct)" + echo "::set-output name=commit::$GITHUB_SHA" + echo "::set-output name=version::$(git describe --tags --always --dirty | cut -c2-)" + echo "::set-output name=tree-state::$(if git diff --quiet; then echo "clean"; else echo "dirty"; fi)" + release: + name: Build and release + needs: + - ldflags_args + outputs: + hashes: ${{ steps.hash.outputs.hashes }} + permissions: + contents: write # To add assets to a release. + id-token: write # To do keyless signing with cosign + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v4 + with: + go-version-file: 'go.mod' + - name: Install Syft + uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3 + - name: Install Cosign + uses: sigstore/cosign-installer@v3.1.1 + with: + cosign-release: 'v2.1.1' + - name: Run GoReleaser + id: run-goreleaser + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} + VERSION: ${{ needs.ldflags_args.outputs.version }} + COMMIT: ${{ needs.ldflags_args.outputs.commit }} + COMMIT_DATE: ${{ needs.ldflags_args.outputs.commit-date }} + TREE_STATE: ${{ needs.ldflags_args.outputs.tree-state }} + + - name: Generate subject + id: hash + env: + ARTIFACTS: "${{ steps.run-goreleaser.outputs.artifacts }}" + run: | + set -euo pipefail + hashes=$(echo $ARTIFACTS | jq --raw-output '.[] | {name, "digest": (.extra.Digest // .extra.Checksum)} | select(.digest) | {digest} + {name} | join(" ") | sub("^sha256:";"")' | base64 -w0) + if test "$hashes" = ""; then # goreleaser < v1.13.0 + checksum_file=$(echo "$ARTIFACTS" | jq -r '.[] | select (.type=="Checksum") | .path') + hashes=$(cat $checksum_file | base64 -w0) + fi + echo "hashes=$hashes" >> $GITHUB_OUTPUT + provenance: + name: Generate provenance (SLSA3) + needs: + - release + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0 + with: + base64-subjects: "${{ needs.release.outputs.hashes }}" + upload-assets: true # upload to a new release + private-repository: true # remove this line after going public + verification: + name: Verify provenance of assets (SLSA3) + needs: + - release + - provenance + runs-on: ubuntu-latest + permissions: read-all + steps: + - name: Install the SLSA verifier + uses: slsa-framework/slsa-verifier/actions/installer@v2.4.0 + - name: Download assets + env: + GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + CHECKSUMS: "${{ needs.release.outputs.hashes }}" + ATT_FILE_NAME: "${{ needs.provenance.outputs.provenance-name }}" + run: | + set -euo pipefail + checksums=$(echo "$CHECKSUMS" | base64 -d) + while read -r line; do + fn=$(echo $line | cut -d ' ' -f2) + echo "Downloading $fn" + gh -R "$GITHUB_REPOSITORY" release download "$GITHUB_REF_NAME" -p "$fn" + done <<<"$checksums" + gh -R "$GITHUB_REPOSITORY" release download "$GITHUB_REF_NAME" -p "$ATT_FILE_NAME" + - name: Verify assets + env: + CHECKSUMS: "${{ needs.release.outputs.hashes }}" + PROVENANCE: "${{ needs.provenance.outputs.provenance-name }}" + run: | + set -euo pipefail + checksums=$(echo "$CHECKSUMS" | base64 -d) + while read -r line; do + fn=$(echo $line | cut -d ' ' -f2) + echo "Verifying SLSA provenance for $fn" + slsa-verifier verify-artifact --provenance-path "$PROVENANCE" \ + --source-uri "github.com/$GITHUB_REPOSITORY" \ + --source-tag "$GITHUB_REF_NAME" \ + "$fn" + done <<<"$checksums" diff --git a/.github/workflows/slsa-go-releaser.yml b/.github/workflows/slsa-go-releaser.yml deleted file mode 100644 index cef8c89b68..0000000000 --- a/.github/workflows/slsa-go-releaser.yml +++ /dev/null @@ -1,94 +0,0 @@ -# This workflow compiles your mediator server and medic using a SLSA3 compliant -# build and then verifies the provenance of the built artifacts. -# It releases the following architectures: amd64, arm64, and armv7 on Linux, -# Windows, and macOS. -# The provenance file can be verified using https://github.com/slsa-framework/slsa-verifier. -# For more information about SLSA and how it improves the supply-chain, visit slsa.dev. - -name: SLSA Go releaser -on: - workflow_dispatch: - release: - types: [created] - -permissions: read-all - -jobs: - # Generate ldflags dynamically. - # Optional: only needed for ldflags. - args: - runs-on: ubuntu-latest - outputs: - commit-date: ${{ steps.ldflags.outputs.commit-date }} - commit: ${{ steps.ldflags.outputs.commit }} - version: ${{ steps.ldflags.outputs.version }} - tree-state: ${{ steps.ldflags.outputs.tree-state }} - steps: - - id: checkout - uses: actions/checkout@v4 # tag=v2.3.4 - with: - fetch-depth: 0 - - id: ldflags - run: | - echo "commit-date=$(git log --date=iso8601-strict -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" - echo "commit=$GITHUB_SHA" >> "$GITHUB_OUTPUT" - echo "version=$(git describe --tags --always --dirty | cut -c2-)" >> "$GITHUB_OUTPUT" - echo "tree-state=$(if git diff --quiet; then echo "clean"; else echo "dirty"; fi)" >> "$GITHUB_OUTPUT" - - # Trusted builder. - build: - permissions: - id-token: write # To sign the provenance. - contents: write # To upload assets to release. - actions: read # To read the workflow path. - needs: args - strategy: - matrix: - os: - - linux - - windows - - darwin - arch: - - amd64 - - arm64 - uses: slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml@v1.9.0 - - with: - go-version: '1.20' - private-repository: true - # Optional: only needed if using ldflags. - evaluated-envs: "COMMIT_DATE:${{needs.args.outputs.commit-date}}, COMMIT:${{needs.args.outputs.commit}}, VERSION:${{needs.args.outputs.version}}, TREE_STATE:${{needs.args.outputs.tree-state}}" - config-file: .slsa-goreleaser/${{matrix.os}}-${{matrix.arch}}.yml - - verification: - needs: - - build - runs-on: ubuntu-latest - permissions: read-all - steps: - - name: Install the verifier - uses: slsa-framework/slsa-verifier/actions/installer@v2.4.0 - - - name: Download assets - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ATT_FILE_NAME: "${{ needs.build.outputs.go-binary-name }}.intoto.jsonl" - ARTIFACT: ${{ needs.build.outputs.go-binary-name }} - run: | - set -euo pipefail - - gh -R "$GITHUB_REPOSITORY" release download "$GITHUB_REF_NAME" -p $ARTIFACT - gh -R "$GITHUB_REPOSITORY" release download "$GITHUB_REF_NAME" -p "$ATT_FILE_NAME" - - - name: Verify assets - env: - ARTIFACT: ${{ needs.build.outputs.go-binary-name }} - ATT_FILE_NAME: "${{ needs.build.outputs.go-binary-name }}.intoto.jsonl" - run: | - set -euo pipefail - - echo "Verifying $ARTIFACT using $ATT_FILE_NAME" - slsa-verifier verify-artifact --provenance-path "$ATT_FILE_NAME" \ - --source-uri "github.com/$GITHUB_REPOSITORY" \ - --source-tag "$GITHUB_REF_NAME" \ - "$ARTIFACT" diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000000..7a351b3aa6 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,82 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com + +# The lines bellow are called `modelines`. See `:help modeline` +# Feel free to remove those if you don't want/need to use them. +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +# vim: set ts=2 sw=2 tw=0 fo=cnqoj +project_name: medic +before: + hooks: + - go mod tidy + - go generate ./... +# This section defines the build matrix. +builds: + - env: + - GO111MODULE=on + - CGO_ENABLED=0 + flags: + - -trimpath + - -tags=netgo + ldflags: + - "-X main.Version={{ .Env.VERSION }}" + - "-X main.Commit={{ .Env.COMMIT }}" + - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" + - "-X main.TreeState={{ .Env.TREE_STATE }}" + goos: + - linux + - windows + - darwin + goarch: + - amd64 + - arm64 + main: ./cmd/cli +# This section defines the release format. +archives: + - format: tar.gz # we can use binary, but it seems there's an issue where goreleaser skips the sboms + name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" # "{{ .Binary }}-{{ .Os }}-{{ .Arch }}" + format_overrides: + - goos: windows + format: zip +# This section defines how to release to homebrew. +brews: + - homepage: 'https://github.com/stacklok/mediator' + description: 'Medic is the client CLI for interacting with Mediator by Stacklok.' + folder: Formula + commit_author: + name: 'Stacklok, Inc.' + email: contact@stacklok.com + repository: + owner: stacklok + name: homebrew-tap + token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}" + test: | + system "#{bin}/medic --help" +# This section defines whether we want to release the source code too. +source: + enabled: true +# This section defines how to generate the changelog +changelog: + sort: asc + use: github +# This section defines for which artifact types to generate SBOMs. +sboms: + - artifacts: archive +# This section defines the release policy. +release: + # If set to auto, will mark the release as not ready for production + # in case there is an indicator for this in the tag e.g. v1.0.0-rc1 + prerelease: auto + github: + owner: stacklok + name: mediator +# This section defines how and which artifacts we want to sign for the release. +signs: + - cmd: cosign + args: + - "sign-blob" + - "--output-signature=${signature}" + - "${artifact}" + - "--yes" # needed on cosign 2.0.0+ + artifacts: archive + output: true diff --git a/.slsa-goreleaser/darwin-amd64.yml b/.slsa-goreleaser/darwin-amd64.yml deleted file mode 100644 index fcc507bb07..0000000000 --- a/.slsa-goreleaser/darwin-amd64.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Version for this file. -version: 1 - -# (Optional) List of env variables used during compilation. -env: - - GO111MODULE=on - - CGO_ENABLED=0 - -# (Optional) Flags for the compiler. -flags: - - -trimpath - - -tags=netgo - -# The OS to compile for. `GOOS` env variable will be set to this value. -goos: darwin - -# The architecture to compile for. `GOARCH` env variable will be set to this value. -goarch: amd64 - -# Binary output name. -# {{ .Os }} will be replaced by goos field in the config file. -# {{ .Arch }} will be replaced by goarch field in the config file. -main: ./cmd/cli -binary: medic-{{ .Os }}-{{ .Arch }} - -# (Optional) ldflags generated dynamically in the workflow, and set as the `evaluated-envs` input variables in the workflow. -ldflags: - - "-X main.Version={{ .Env.VERSION }}" - - "-X main.Commit={{ .Env.COMMIT }}" - - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" - - "-X main.TreeState={{ .Env.TREE_STATE }}" \ No newline at end of file diff --git a/.slsa-goreleaser/darwin-arm64.yml b/.slsa-goreleaser/darwin-arm64.yml deleted file mode 100644 index 7370039909..0000000000 --- a/.slsa-goreleaser/darwin-arm64.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Version for this file. -version: 1 - -# (Optional) List of env variables used during compilation. -env: - - GO111MODULE=on - - CGO_ENABLED=0 - -# (Optional) Flags for the compiler. -flags: - - -trimpath - - -tags=netgo - -# The OS to compile for. `GOOS` env variable will be set to this value. -goos: darwin - -# The architecture to compile for. `GOARCH` env variable will be set to this value. -goarch: arm64 - -# Binary output name. -# {{ .Os }} will be replaced by goos field in the config file. -# {{ .Arch }} will be replaced by goarch field in the config file. -main: ./cmd/cli -binary: medic-{{ .Os }}-{{ .Arch }} - -# (Optional) ldflags generated dynamically in the workflow, and set as the `evaluated-envs` input variables in the workflow. -ldflags: - - "-X main.Version={{ .Env.VERSION }}" - - "-X main.Commit={{ .Env.COMMIT }}" - - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" - - "-X main.TreeState={{ .Env.TREE_STATE }}" diff --git a/.slsa-goreleaser/linux-amd64.yml b/.slsa-goreleaser/linux-amd64.yml deleted file mode 100644 index 4fc6597196..0000000000 --- a/.slsa-goreleaser/linux-amd64.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Version for this file. -version: 1 - -# (Optional) List of env variables used during compilation. -env: - - GO111MODULE=on - - CGO_ENABLED=0 - -# (Optional) Flags for the compiler. -flags: - - -trimpath - - -tags=netgo - -# The OS to compile for. `GOOS` env variable will be set to this value. -goos: linux - -# The architecture to compile for. `GOARCH` env variable will be set to this value. -goarch: amd64 - -# Binary output name. -# {{ .Os }} will be replaced by goos field in the config file. -# {{ .Arch }} will be replaced by goarch field in the config file. -main: ./cmd/cli -binary: medic-{{ .Os }}-{{ .Arch }} - -# (Optional) ldflags generated dynamically in the workflow, and set as the `evaluated-envs` input variables in the workflow. -# ldflags: -# - "-X main.Version={{ .Env.VERSION }}" -# - "-X main.Commit={{ .Env.COMMIT }}" -# - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" -# - "-X main.TreeState={{ .Env.TREE_STATE }}" \ No newline at end of file diff --git a/.slsa-goreleaser/linux-arm64.yml b/.slsa-goreleaser/linux-arm64.yml deleted file mode 100644 index cd8b63c008..0000000000 --- a/.slsa-goreleaser/linux-arm64.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Version for this file. -version: 1 - -# (Optional) List of env variables used during compilation. -env: - - GO111MODULE=on - - CGO_ENABLED=0 - -# (Optional) Flags for the compiler. -flags: - - -trimpath - - -tags=netgo - -# The OS to compile for. `GOOS` env variable will be set to this value. -goos: linux - -# The architecture to compile for. `GOARCH` env variable will be set to this value. -goarch: arm64 - -# Binary output name. -# {{ .Os }} will be replaced by goos field in the config file. -# {{ .Arch }} will be replaced by goarch field in the config file. -main: ./cmd/cli -binary: medic-{{ .Os }}-{{ .Arch }} - -# (Optional) ldflags generated dynamically in the workflow, and set as the `evaluated-envs` input variables in the workflow. -ldflags: - - "-X main.Version={{ .Env.VERSION }}" - - "-X main.Commit={{ .Env.COMMIT }}" - - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" - - "-X main.TreeState={{ .Env.TREE_STATE }}" \ No newline at end of file diff --git a/.slsa-goreleaser/windows-amd64.yml b/.slsa-goreleaser/windows-amd64.yml deleted file mode 100644 index 4bf70d15da..0000000000 --- a/.slsa-goreleaser/windows-amd64.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Version for this file. -version: 1 - -# (Optional) List of env variables used during compilation. -env: - - GO111MODULE=on - - CGO_ENABLED=0 - -# (Optional) Flags for the compiler. -flags: - - -trimpath - - -tags=netgo - -# The OS to compile for. `GOOS` env variable will be set to this value. -goos: windows - -# The architecture to compile for. `GOARCH` env variable will be set to this value. -goarch: amd64 - -# Binary output name. -# {{ .Os }} will be replaced by goos field in the config file. -# {{ .Arch }} will be replaced by goarch field in the config file. -main: ./cmd/cli -binary: medic-{{ .Os }}-{{ .Arch }} - -# (Optional) ldflags generated dynamically in the workflow, and set as the `evaluated-envs` input variables in the workflow. -ldflags: - - "-X main.Version={{ .Env.VERSION }}" - - "-X main.Commit={{ .Env.COMMIT }}" - - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" - - "-X main.TreeState={{ .Env.TREE_STATE }}" \ No newline at end of file diff --git a/.slsa-goreleaser/windows-arm64.yml b/.slsa-goreleaser/windows-arm64.yml deleted file mode 100644 index 8aa2ff50fa..0000000000 --- a/.slsa-goreleaser/windows-arm64.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Version for this file. -version: 1 - -# (Optional) List of env variables used during compilation. -env: - - GO111MODULE=on - - CGO_ENABLED=0 - -# (Optional) Flags for the compiler. -flags: - - -trimpath - - -tags=netgo - -# The OS to compile for. `GOOS` env variable will be set to this value. -goos: windows - -# The architecture to compile for. `GOARCH` env variable will be set to this value. -goarch: arm64 - -# Binary output name. -# {{ .Os }} will be replaced by goos field in the config file. -# {{ .Arch }} will be replaced by goarch field in the config file. -main: ./cmd/cli -binary: medic-{{ .Os }}-{{ .Arch }} - - -# (Optional) ldflags generated dynamically in the workflow, and set as the `evaluated-envs` input variables in the workflow. -ldflags: - - "-X main.Version={{ .Env.VERSION }}" - - "-X main.Commit={{ .Env.COMMIT }}" - - "-X main.CommitDate={{ .Env.COMMIT_DATE }}" - - "-X main.TreeState={{ .Env.TREE_STATE }}" \ No newline at end of file