From 259426efd4e4a70a64217cf1a80df96e1dfeb9bd Mon Sep 17 00:00:00 2001 From: Andres Almiray Date: Sat, 21 Dec 2024 18:00:57 +0100 Subject: [PATCH] Add SLSA generator for Rust --- .github/workflows/builder_slsa3.yml | 129 +++++++++++++++++++++++++++ README.adoc | 65 ++++++++++++++ internal/builders/rustzig/action.yml | 117 ++++++++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 .github/workflows/builder_slsa3.yml create mode 100644 internal/builders/rustzig/action.yml diff --git a/.github/workflows/builder_slsa3.yml b/.github/workflows/builder_slsa3.yml new file mode 100644 index 0000000..798e6ea --- /dev/null +++ b/.github/workflows/builder_slsa3.yml @@ -0,0 +1,129 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright 2020-2024 The JReleaser authors. +# +# 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 +# +# https://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. +# + +name: JReleaser Rust SLSA Generator + +on: + workflow_call: + inputs: + project-version: + description: 'The project version' + required: true + type: string + branch: + description: 'The working branch' + required: false + default: 'main' + type: string + tag-or-ref: + description: 'Tag or ref to checkout' + required: false + type: string + rust-version: + description: 'Rust version' + required: false + default: stable + type: string + zig-version: + description: 'Zig version' + required: false + default: latest + type: string + jreleaser-version: + description: 'JReleaser version' + required: false + default: latest + type: string + rekor-log-public: + description: 'private' + required: false + type: boolean + default: false + secrets: + github-token: + required: true + +jobs: + slsa-setup: + permissions: + id-token: write # For token creation. + outputs: + slsa-token: ${{ steps.generate.outputs.slsa-token }} + runs-on: ubuntu-latest + steps: + - name: Generate the token + id: generate + uses: slsa-framework/slsa-github-generator/actions/delegator/setup-generic@v2.0.0 + with: + slsa-workflow-recipient: 'delegator_generic_slsa3.yml' + slsa-rekor-log-public: ${{ inputs.rekor-log-public }} + slsa-runner-label: 'ubuntu-latest' + slsa-build-action-path: './internal/builders/rustzig' + slsa-workflow-inputs: ${{ toJson(inputs) }} + + slsa-run: + needs: [ slsa-setup ] + permissions: + id-token: write # For signing. + contents: write # For asset uploads. + actions: read # For the entrypoint. + packages: write + uses: slsa-framework/slsa-github-generator/.github/workflows/delegator_generic_slsa3.yml@v2.0.0 + with: + slsa-token: ${{ needs.slsa-setup.outputs.slsa-token }} + secrets: + secret1: ${{ secrets.github-token }} + + slsa-upload: + needs: [ slsa-run ] + runs-on: ubuntu-latest + steps: + - name: Checkout branch + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v 4.1.4 + with: + fetch-depth: 0 + ref: ${{ inputs.branch }} + + - name: Download provenance + uses: slsa-framework/slsa-github-generator/actions/nodejs/secure-attestations-download@v2.0.0 + with: + name: ${{ needs.slsa-run.outputs.attestations-download-name }} + path: slsa + sha256: ${{ needs.slsa-run.outputs.attestations-download-sha256 }} + + - name: Download JReleaser output + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v 4.1.4 + with: + name: jreleaser-release + path: jreleaser-release + + - name: Resolve tagName + shell: bash + run: | + echo "JRELEASER_TAG_NAME=$(grep tagName jreleaser-release/output.properties | awk -F= '{print $2}')" >> $GITHUB_ENV + + - name: Release provenance + uses: jreleaser/release-action@f69e545b05f149483cecb2fb81866247992694b8 # v 2.4.2 + with: + version: ${{ inputs.jreleaser-version }} + arguments: | + release --auto-config --update --skip-tag --branch ${{ inputs.branch }} --tag-name ${{ env.JRELEASER_TAG_NAME }} \ + --update-section=ASSETS --skip-checksums --file slsa/${{ needs.slsa-run.outputs.attestations-download-name }}/*-attestation.intoto.build.slsa + env: + JRELEASER_PROJECT_VERSION: ${{ inputs.project-version }} + JRELEASER_GITHUB_TOKEN: ${{ secrets.github-token }} diff --git a/README.adoc b/README.adoc index 6de3660..c17e283 100644 --- a/README.adoc +++ b/README.adoc @@ -153,3 +153,68 @@ Additional environment variables may be needed depending on your specific setup, with GPG or announcing a release via Twitter. Review the docs at link:https://jreleaser.org[] to find more about these variables and how to set them up. +=== SLSA Builder + +A custom link:https://github.com/slsa-framework/[SLSA builder] is available for Rust projects that rely on Zig as linker. +The following snippet shows the minimum configuration to run the builder on GitHub Actions. + +[source,yaml] +---- + release: + permissions: + contents: write + id-token: write + actions: read + packages: write + uses: jreleaser/release-action/.github/workflows/builder_slsa3.yml@v1.0.0-rustzig + with: + project-version: ${{ inputs.version }} + rekor-log-public: true + secrets: + github-token: ${{ secrets.GITHUB_TOKEN }} +---- + +It's expected that the JReleaser configuration defines build instructions using the `hooks` feature, such as + +[source,yaml] +.jreleaser.yml +---- +matrix: + rows: + - { target: aarch64-apple-darwin, platform: osx-aarch_64 } + - { target: x86_64-apple-darwin, platform: osx-x86_64 } + - { target: aarch64-unknown-linux-gnu, platform: linux-aarch_64 } + - { target: x86_64-unknown-linux-gnu, platform: linux-x86_64 } + - { target: x86_64-pc-windows-gnu, platform: windows-x86_64 } + +hooks: + script: + before: + - run: | + rustup target add {{ matrix.target }} + cargo install --locked cargo-zigbuild + cargo zigbuild --target {{ matrix.target }} + applyDefaultMatrix: true + verbose: true + filter: + includes: ['assemble'] + +assemble: + archive: + helloworld: + active: ALWAYS + formats: [ ZIP ] + applyDefaultMatrix: true + archiveName: '{{distributionName}}-{{projectVersion}}-{{ matrix.target }}' + fileSets: + - input: 'target/{{ matrix.target }}' + output: 'bin' + includes: [ 'helloworld{.exe,}' ] + - input: '.' + includes: [ 'LICENSE' ] + +distributions: + helloworld: + executable: + windowsExtension: exe +---- diff --git a/internal/builders/rustzig/action.yml b/internal/builders/rustzig/action.yml new file mode 100644 index 0000000..9d16afe --- /dev/null +++ b/internal/builders/rustzig/action.yml @@ -0,0 +1,117 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright 2020-2024 The JReleaser authors. +# +# 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 +# +# https://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. +# + +name: JReleaser Rust Builder + +description: 'JReleaser Rust Builder' + +inputs: + slsa-workflow-inputs: + description: 'All the inputs' + required: true + slsa-layout-file: + description: 'Location to store the layout content' + required: true + slsa-workflow-secret1: {} + slsa-workflow-secret2: {} + slsa-workflow-secret3: {} + slsa-workflow-secret4: {} + slsa-workflow-secret5: {} + slsa-workflow-secret6: {} + slsa-workflow-secret7: {} + slsa-workflow-secret8: {} + slsa-workflow-secret9: {} + slsa-workflow-secret10: {} + slsa-workflow-secret11: {} + slsa-workflow-secret12: {} + slsa-workflow-secret13: {} + slsa-workflow-secret14: {} + slsa-workflow-secret15: {} + +runs: + using: 'composite' + steps: + - name: Checkout branch + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v 4.1.4 + with: + fetch-depth: 0 + ref: ${{ fromJson(inputs.slsa-workflow-inputs).branch }} + + - name: Checkout ref + if: ${{ fromJson(inputs.slsa-workflow-inputs).tag-or-ref != '' }} + shell: bash + run: git checkout ${{ fromJson(inputs.slsa-workflow-inputs).tag-or-ref }} + + - name: Setup Zig + uses: mlugg/setup-zig@a67e68dc5c8281d9608136d3d7ca1b282213e4ac # v 1.2.1 + with: + version: ${{ fromJson(inputs.slsa-workflow-inputs).zig-version }} + + - name: Setup Rust + uses: actions-rs/toolchain@b2417cde72dcf67f306c0ae8e0828a81bf0b189f # v 1.0.6 + with: + toolchain: ${{ fromJson(inputs.slsa-workflow-inputs).rust-version }} + + - name: Setup zigbuild + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v 1.0.1 + with: + command: install + args: --locked cargo-zigbuild + + - name: Assemble + uses: jreleaser/release-action@f69e545b05f149483cecb2fb81866247992694b8 # v 2.4.2 + with: + version: ${{ fromJson(inputs.slsa-workflow-inputs).jreleaser-version }} + arguments: assemble + env: + CI: 'true' + JRELEASER_PROJECT_VERSION: ${{ fromJson(inputs.slsa-workflow-inputs).project-version }} + + - name: JReleaser output + if: always() + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v 4.3.3 + with: + name: jreleaser-assemble + path: | + out/jreleaser/trace.log + out/jreleaser/output.properties + + - name: Release + uses: jreleaser/release-action@f69e545b05f149483cecb2fb81866247992694b8 # v 2.4.2 + with: + version: ${{ fromJson(inputs.slsa-workflow-inputs).jreleaser-version }} + arguments: release + setup-java: false + env: + JRELEASER_PROJECT_VERSION: ${{ fromJson(inputs.slsa-workflow-inputs).project-version }} + JRELEASER_GITHUB_TOKEN: ${{ inputs.slsa-workflow-secret1 }} + JRELEASER_CATALOG_SLSA_ACTIVE: ALWAYS + + - name: JReleaser output + if: always() + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v 4.3.3 + with: + name: jreleaser-release + path: | + out/jreleaser/trace.log + out/jreleaser/output.properties + + - name: Rename attestation file + shell: bash + run: | + mv out/jreleaser/catalogs/slsa/*.intoto ${{ inputs.slsa-layout-file }}