From e3ff60a00c8591c8bd99826192c120df22abaaf5 Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Mon, 7 Apr 2025 14:13:28 +0200 Subject: [PATCH] feat: add SBOM generation and attestation to GitHub workflow Change-Id: I2e15d7322ddec933bbc9bd7880abba9b0842719f Signed-off-by: Thomas Kosiewski --- .github/workflows/ci.yaml | 27 ++++++++++++++ .github/workflows/release.yaml | 67 ++++++++++++++++++++++++++++++---- scripts/build_docker.sh | 13 +------ 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d1d5bf9c2959c..d25cb84173326 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1180,6 +1180,33 @@ jobs: done fi + - name: SBOM Generation and Attestation + if: github.ref == 'refs/heads/main' + env: + COSIGN_EXPERIMENTAL: 1 + run: | + set -euxo pipefail + + # Define image base and tags + IMAGE_BASE="ghcr.io/coder/coder-preview" + TAGS=("${{ steps.build-docker.outputs.tag }}" "main" "latest") + + # Generate and attest SBOM for each tag + for tag in "${TAGS[@]}"; do + IMAGE="${IMAGE_BASE}:${tag}" + SBOM_FILE="coder_sbom_${tag//[:\/]/_}.spdx.json" + + echo "Generating SBOM for image: ${IMAGE}" + syft "${IMAGE}" -o spdx-json > "${SBOM_FILE}" + + echo "Attesting SBOM to image: ${IMAGE}" + cosign clean "${IMAGE}" + cosign attest --type spdxjson \ + --predicate "${SBOM_FILE}" \ + --yes \ + "${IMAGE}" + done + # GitHub attestation provides SLSA provenance for the Docker images, establishing a verifiable # record that these images were built in GitHub Actions with specific inputs and environment. # This complements our existing cosign attestations which focus on SBOMs. diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 07a57b8ad939b..eb3983dac807f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -496,6 +496,39 @@ jobs: env: CODER_BASE_IMAGE_TAG: ${{ steps.image-base-tag.outputs.tag }} + - name: SBOM Generation and Attestation + if: ${{ !inputs.dry_run }} + env: + COSIGN_EXPERIMENTAL: "1" + run: | + set -euxo pipefail + + # Generate SBOM for multi-arch image with version in filename + echo "Generating SBOM for multi-arch image: ${{ steps.build_docker.outputs.multiarch_image }}" + syft "${{ steps.build_docker.outputs.multiarch_image }}" -o spdx-json > coder_${{ steps.version.outputs.version }}_sbom.spdx.json + + # Attest SBOM to multi-arch image + echo "Attesting SBOM to multi-arch image: ${{ steps.build_docker.outputs.multiarch_image }}" + cosign clean "${{ steps.build_docker.outputs.multiarch_image }}" + cosign attest --type spdxjson \ + --predicate coder_${{ steps.version.outputs.version }}_sbom.spdx.json \ + --yes \ + "${{ steps.build_docker.outputs.multiarch_image }}" + + # If latest tag was created, also attest it + if [[ "${{ steps.build_docker.outputs.created_latest_tag }}" == "true" ]]; then + latest_tag="$(./scripts/image_tag.sh --version latest)" + echo "Generating SBOM for latest image: ${latest_tag}" + syft "${latest_tag}" -o spdx-json > coder_latest_sbom.spdx.json + + echo "Attesting SBOM to latest image: ${latest_tag}" + cosign clean "${latest_tag}" + cosign attest --type spdxjson \ + --predicate coder_latest_sbom.spdx.json \ + --yes \ + "${latest_tag}" + fi + - name: GitHub Attestation for Docker image id: attest_main if: ${{ !inputs.dry_run }} @@ -612,16 +645,27 @@ jobs: fi declare -p publish_args + # Build the list of files to publish + files=( + ./build/*_installer.exe + ./build/*.zip + ./build/*.tar.gz + ./build/*.tgz + ./build/*.apk + ./build/*.deb + ./build/*.rpm + ./coder_${{ steps.version.outputs.version }}_sbom.spdx.json + ) + + # Only include the latest SBOM file if it was created + if [[ "${{ steps.build_docker.outputs.created_latest_tag }}" == "true" ]]; then + files+=(./coder_latest_sbom.spdx.json) + fi + ./scripts/release/publish.sh \ "${publish_args[@]}" \ --release-notes-file "$CODER_RELEASE_NOTES_FILE" \ - ./build/*_installer.exe \ - ./build/*.zip \ - ./build/*.tar.gz \ - ./build/*.tgz \ - ./build/*.apk \ - ./build/*.deb \ - ./build/*.rpm + "${files[@]}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CODER_GPG_RELEASE_KEY_BASE64: ${{ secrets.GPG_RELEASE_KEY_BASE64 }} @@ -663,6 +707,15 @@ jobs: ./build/*.apk ./build/*.deb ./build/*.rpm + ./coder_${{ steps.version.outputs.version }}_sbom.spdx.json + retention-days: 7 + + - name: Upload latest sbom artifact to actions (if dry-run) + if: inputs.dry_run && steps.build_docker.outputs.created_latest_tag == 'true' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: latest-sbom-artifact + path: ./coder_latest_sbom.spdx.json retention-days: 7 - name: Send repository-dispatch event diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh index 7f1ba93840403..14d45d0913b6b 100755 --- a/scripts/build_docker.sh +++ b/scripts/build_docker.sh @@ -153,17 +153,6 @@ if [[ "$push" == 1 ]]; then docker push "$image_tag" 1>&2 fi -log "--- Generating SBOM for Docker image ($image_tag)" -syft "$image_tag" -o spdx-json >"${image_tag//[:\/]/_}.spdx.json" - -if [[ "$push" == 1 ]]; then - log "--- Attesting SBOM to Docker image for $arch ($image_tag)" - COSIGN_EXPERIMENTAL=1 cosign clean "$image_tag" - - COSIGN_EXPERIMENTAL=1 cosign attest --type spdxjson \ - --predicate "${image_tag//[:\/]/_}.spdx.json" \ - --yes \ - "$image_tag" -fi +# SBOM generation and attestation moved to the GitHub workflow echo "$image_tag" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy