diff --git a/.github/workflows/homebrew.yml b/.github/workflows/homebrew.yml index a1d1d994..072d0ec4 100644 --- a/.github/workflows/homebrew.yml +++ b/.github/workflows/homebrew.yml @@ -23,20 +23,43 @@ jobs: exit 1 fi - update-brew: + brew_formula: needs: enforce_stable_semver - if: github.repository_owner == 'openziti' - runs-on: ubuntu-latest + if: github.repository_owner == 'openziti' || github.repository_owner == 'openziti-test-kitchen' + runs-on: ubuntu-24.04 steps: - - name: Extract Version - id: extract-version - run: | - echo "tag-name=${GITHUB_REF#refs/tags/}" | tee -a ${GITHUB_OUTPUT} - - uses: mislav/bump-homebrew-formula-action@v3.1 - if: ${{ !contains(github.ref, '-') }} + - name: Get Checksums File + shell: bash + run: | + curl -sSLf -o checksums.sha256.txt \ + https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/checksums.sha256.txt + + - name: Get Source Archive + shell: bash + run: | + curl -sSLf -o source-${{ github.ref_name }}.tar.gz \ + https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/source-${{ github.ref_name }}.tar.gz + + - name: Verify Source Archive Checksum + shell: bash + run: | + shasum --algorithm 256 --ignore-missing --check checksums.sha256.txt + + - name: Extract Source Archive Checksum + id: source + shell: bash + run: | + CHECKSUM=$(grep -E "\bsource-${{ github.ref_name }}\.tar\.gz$" checksums.sha256.txt | cut -d' ' -f1) + echo "sha256=${CHECKSUM}" | tee -a "$GITHUB_OUTPUT" + + - name: Upload Release Source Archive to Homebrew + uses: mislav/bump-homebrew-formula-action@v3.2 with: formula-name: zrok - download-url: https://github.com/openziti/zrok/archive/refs/tags/${{ steps.extract-version.outputs.tag-name }}.tar.gz + formula-path: Formula/z/zrok.rb + download-url: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/source-${{ github.ref_name }}.tar.gz + download-sha256: ${{ steps.source.outputs.sha256 }} + homebrew-tap: ${{ vars.ZROK_BREW_TAP || 'Homebrew/homebrew-core' }} env: COMMITTER_TOKEN: ${{ secrets.BREW_COMMITTER_TOKEN }} diff --git a/.github/workflows/publish-docker-images.yml b/.github/workflows/publish-docker-images.yml index 4faf43c1..8f8f0b5b 100644 --- a/.github/workflows/publish-docker-images.yml +++ b/.github/workflows/publish-docker-images.yml @@ -11,13 +11,18 @@ on: jobs: publish-docker-images: runs-on: ubuntu-24.04 + permissions: + id-token: write # need write to get OIDC token for generating attestations + attestations: write # need write to create attestations env: + REGISTRY: docker.io RELEASE_REF: ${{ inputs.zrok-version }} steps: # compose the semver string without leading "refs/tags" or "v" so we can predict the # release artifact filename - name: Set zrok Version Semver from Tag Ref id: semver + shell: bash run: | echo "zrok_semver=${RELEASE_REF#v}" | tee -a $GITHUB_OUTPUT @@ -37,6 +42,7 @@ jobs: path: dist/arm64/linux - name: Unpack the Release Artifacts + shell: bash run: | for TGZ in dist/{amd,arm}64/linux; do tar -xvzf ${TGZ}/*.tar.gz -C ${TGZ} @@ -54,6 +60,7 @@ jobs: - name: Login to Docker Hub uses: docker/login-action@v3 with: + registry: ${{ env.REGISTRY}} username: ${{ vars.DOCKER_HUB_API_USER || secrets.DOCKER_HUB_API_USER }} password: ${{ secrets.DOCKER_HUB_API_TOKEN }} @@ -62,14 +69,14 @@ jobs: ZROK_CONTAINER_IMAGE_REPO: ${{ vars.ZROK_CONTAINER_IMAGE_REPO || 'openziti/zrok' }} ZROK_CONTAINER_IMAGE_TAG: ${{ steps.semver.outputs.zrok_semver }} id: tagprep_cli + shell: bash run: | DOCKER_TAGS="${ZROK_CONTAINER_IMAGE_REPO}:${ZROK_CONTAINER_IMAGE_TAG}" echo "DOCKER_TAGS=${DOCKER_TAGS}" | tee -a $GITHUB_OUTPUT - # this is the CLI image with the Linux binary for each - # arch that was downloaded in ./dist/ - name: Build & Push Multi-Platform CLI Container Image to Hub - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 + id: push with: builder: ${{ steps.buildx.outputs.name }} context: ${{ github.workspace }}/ @@ -79,4 +86,15 @@ jobs: build-args: | DOCKER_BUILD_DIR=./docker/images/zrok ARTIFACTS_DIR=./dist + provenance: mode=max + sbom: true push: true + + - name: Publish Attestations to GitHub + uses: actions/attest-build-provenance@v1 + env: + IMAGE_REPO: ${{ vars.ZROK_CONTAINER_IMAGE_REPO || 'openziti/zrok' }} + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_REPO }} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3d67a6d..78384135 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,10 +5,6 @@ on: tags: - 'v*.*.*' -# grant write permission to GITHUB_TOKEN for goreleaser -permissions: - contents: write - env: ZITI_DEB_TEST_REPO: ${{ vars.ZITI_DEB_TEST_REPO || 'zitipax-openziti-deb-test' }} ZITI_RPM_TEST_REPO: ${{ vars.ZITI_RPM_TEST_REPO || 'zitipax-openziti-rpm-test' }} @@ -287,23 +283,59 @@ jobs: draft-release: runs-on: ubuntu-latest needs: call-publish-docker-images + permissions: + contents: write # need write to draft the release + id-token: write # need write to get OIDC token for generating attestations + attestations: write # need write to create attestations steps: - uses: actions/checkout@v4 - run: | mkdir -p ./automated-release-build + - name: Fetch Source Archive + shell: bash + run: | + curl -sSLf -o ./automated-release-build/source-${{ github.ref_name }}.tar.gz \ + https://api.github.com/repos/${{ github.repository }}/tarball/${{ github.ref_name }} + + - name: Build SBOM from Dependency Graph as SPDX JSON + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${{ github.repository }}/dependency-graph/sbom \ + | tee ./automated-release-build/sbom-${{ github.ref_name }}.spdx.json + - uses: actions/download-artifact@v4 with: path: ./automated-release-build merge-multiple: true pattern: release-builds-* - - run: | - ls -lAR ./automated-release-build/ - shasum ./automated-release-build/* > ./automated-release-build/checksums.txt + - name: Create Checksum Files + shell: bash + run: | - - uses: goreleaser/goreleaser-action@v6 + ls -lAR ./automated-release-build/ + + # create checksum file for the attestations + shasum --algorithm 256 ./automated-release-build/* | tee /tmp/attestation-subjects.sha256.txt + + # create checksum file for the release + cd ./automated-release-build/ + shasum --algorithm 256 ./* | tee ./checksums.sha256.txt + + - name: Attest Build Provenance + uses: actions/attest-build-provenance@v2 + with: + subject-checksums: /tmp/attestation-subjects.sha256.txt + + - name: Draft Release + uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser version: '~> v2' diff --git a/.gitignore b/.gitignore index a830fe64..4566b841 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ .idea .vscode *.db -automated-release-build +/automated-release-build/ etc/dev.yml etc/dev-frontend.yml @@ -10,7 +10,7 @@ etc/dev-frontend.yml node_modules/ # Artifacts -dist/ +/dist/ # Generated files .docusaurus diff --git a/CHANGELOG.md b/CHANGELOG.md index 783d7a76..0bfca0b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,12 +26,22 @@ CHANGE: The protocol for determining valid client versions has been changed. Pre ## v0.4.49 -FIX: Pre-releases are no longer uploaded to the stable Linux package repo. +FIX: Release artifacts now include a reproducible source archive. The archive's download URL is now used by the Homebrew formula when building from source instead of the archive generated on-demand by GitHub (https://github.com/openziti/zrok/issues/858). + +FIX: Pre-releases are no longer uploaded to the stable Linux package repo, and workflows that promote stable release artifacts to downstream distribution channels enforce semver stable release tags, i.e., not having a semver hyphenated prerelease suffix. + +CHANGE: The release `checksums.txt` has been renamed `checksums.sha256.txt` to reflect the use of a collision-resistant algorithm instead of `shasum`'s default algorithm, SHA-1. + +CHANGE: The dependency graph is now published as a release artifact named `sbom-{version}.spdx.json` (https://github.com/openziti/zrok/issues/888). CHANGE: Pre-releases are uploaded to the pre-release Linux package repo and Docker Hub for testing. [RELEASING.md](./RELEASING.md) describes releaser steps and the events they trigger. CHANGE: Linux release binaries are now built on the ziti-builder container image based on Ubuntu Focal 20.04 to preserve backward compatibility as the ubuntu-20.04 GitHub runner is end of life. +CHANGE: Container images now include SLSA and SBOM attestations, and these are also published to the Docker Hub registry (https://github.com/openziti/zrok/issues/890). + +CHANGE: Release binary and text artifacts are now accompanied by provenance attestations (https://github.com/openziti/zrok/issues/889). + ## v0.4.48 FEATURE: The controller configuration now supports a `disable_auto_migration` boolean in the `store` stanza. When set to `true`, the controller will not attempt to auto-migrate (or otherwise validate the migration state) of the underlying database. Leaving `disable_auto_migration` out, or setting it to false will retain the default behavior of auto-migrating when starting the zrok controller. The `zrok admin migrate` command will still perform a migration regardless of how this setting is configured in the controller configuration (https://github.com/openziti/zrok/issues/866)