From f54ae0c509eaaf249df6a2aa645109825337f0a0 Mon Sep 17 00:00:00 2001 From: dervoeti Date: Fri, 26 Jun 2026 10:31:49 +0200 Subject: [PATCH 1/2] feat: generate SLSA provenance for operator images --- template/.github/workflows/build.yaml.j2 | 65 ++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/template/.github/workflows/build.yaml.j2 b/template/.github/workflows/build.yaml.j2 index 17a57e7d..383909c8 100644 --- a/template/.github/workflows/build.yaml.j2 +++ b/template/.github/workflows/build.yaml.j2 @@ -205,6 +205,9 @@ jobs: permissions: id-token: write runs-on: ubuntu-latest + outputs: + oci-index-digest: ${{ steps.publish-oci.outputs.image-index-manifest-digest }} + quay-index-digest: ${{ steps.publish-quay.outputs.image-index-manifest-digest }} steps: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -212,6 +215,7 @@ jobs: persist-credentials: false - name: Publish and Sign Image Index to oci.stackable.tech + id: publish-oci uses: stackabletech/actions/publish-image-index-manifest@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 with: image-registry-uri: oci.stackable.tech @@ -221,6 +225,7 @@ jobs: image-index-manifest-tag: ${{ needs.build-container-image.outputs.operator-version }} - name: Publish and Sign Image Index to quay.io + id: publish-quay uses: stackabletech/actions/publish-image-index-manifest@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 with: image-registry-uri: quay.io @@ -229,6 +234,64 @@ jobs: image-repository: stackable/sdp/${{ env.OPERATOR_NAME }} image-index-manifest-tag: ${{ needs.build-container-image.outputs.operator-version }} + # Generate SLSA build provenance for the multi-arch image index and attach it + # to the published image in each registry. The reusable workflow signs the + # provenance with keyless signing (GitHub Actions as the OIDC identity) and + # pushes the attestation next to the image. + provenance-oci: + name: Generate Provenance for ${{ needs.build-container-image.outputs.operator-version }} (oci.stackable.tech) + if: | + (github.event_name != 'merge_group') + && needs.detect-changes.outputs.detected == 'true' + && !github.event.pull_request.head.repo.fork + needs: + - detect-changes + - build-container-image + - publish-index-manifest + permissions: + actions: read # detect the build workflow that generated the image + id-token: write # mint the OIDC token for keyless signing + packages: write # needed until https://github.com/slsa-framework/slsa-github-generator/issues/1257 is resolved + # MUST be referenced by a @vX.Y.Z tag (not a SHA), otherwise the reusable + # workflow cannot verify its own provenance. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0 + with: + # The 'env' context is not available in job-level 'with' inputs of + # reusable workflow calls (unlike step-level 'with'), so OPERATOR_NAME + # can't be used here and the operator name is templated in directly. + image: oci.stackable.tech/sdp/{[ operator.name }] + digest: ${{ needs.publish-index-manifest.outputs.oci-index-digest }} + registry-username: robot$sdp+github-action-build + secrets: + registry-password: ${{ secrets.HARBOR_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} + + provenance-quay: + name: Generate Provenance for ${{ needs.build-container-image.outputs.operator-version }} (quay.io) + if: | + (github.event_name != 'merge_group') + && needs.detect-changes.outputs.detected == 'true' + && !github.event.pull_request.head.repo.fork + needs: + - detect-changes + - build-container-image + - publish-index-manifest + permissions: + actions: read # detect the build workflow that generated the image + id-token: write # mint the OIDC token for keyless signing + packages: write # needed until https://github.com/slsa-framework/slsa-github-generator/issues/1257 is resolved + # MUST be referenced by a @vX.Y.Z tag (not a SHA), otherwise the reusable + # workflow cannot verify its own provenance. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0 + with: + # The 'env' context is not available in job-level 'with' inputs of + # reusable workflow calls (unlike step-level 'with'), so OPERATOR_NAME + # can't be used here and the operator name is templated in directly. + image: quay.io/stackable/sdp/{[ operator.name }] + digest: ${{ needs.publish-index-manifest.outputs.quay-index-digest }} + registry-username: stackable+robot_sdp_github_action_build + secrets: + registry-password: ${{ secrets.QUAY_ROBOT_SDP_GITHUB_ACTION_BUILD_SECRET }} + publish-helm-chart: name: Package/Publish ${{ needs.build-container-image.outputs.operator-version }} Helm Chart if: | @@ -328,6 +391,8 @@ jobs: - detect-changes - build-container-image - publish-index-manifest + - provenance-oci + - provenance-quay - publish-helm-chart runs-on: ubuntu-latest steps: From 361886f787251f9a5987fe04d077fe18e2a992db Mon Sep 17 00:00:00 2001 From: dervoeti Date: Wed, 1 Jul 2026 15:16:31 +0200 Subject: [PATCH 2/2] chore: Bump stackabletech/actions to v0.16.0 --- .github/workflows/pr_prek.yml | 2 +- template/.github/workflows/build.yaml.j2 | 22 +++++++++---------- .../.github/workflows/integration-test.yml | 4 ++-- template/.github/workflows/pr_prek.yaml.j2 | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pr_prek.yml b/.github/workflows/pr_prek.yml index 04166e26..d7107b71 100644 --- a/.github/workflows/pr_prek.yml +++ b/.github/workflows/pr_prek.yml @@ -17,6 +17,6 @@ jobs: with: persist-credentials: false fetch-depth: 0 - - uses: stackabletech/actions/run-prek@bb86a79a5ab73726d4f047f07452c3307ff0b300 # v0.15.0 + - uses: stackabletech/actions/run-prek@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: hadolint: ${{ env.HADOLINT_VERSION }} diff --git a/template/.github/workflows/build.yaml.j2 b/template/.github/workflows/build.yaml.j2 index 383909c8..123692e0 100644 --- a/template/.github/workflows/build.yaml.j2 +++ b/template/.github/workflows/build.yaml.j2 @@ -48,7 +48,7 @@ jobs: - name: Check for changed files id: check - uses: stackabletech/actions/detect-changes@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/detect-changes@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: patterns: | - '.github/workflows/build.yaml' @@ -164,7 +164,7 @@ jobs: - name: Build Container Image id: build - uses: stackabletech/actions/build-container-image@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/build-container-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-name: ${{ env.OPERATOR_NAME }} image-index-manifest-tag: ${{ steps.version.outputs.OPERATOR_VERSION }} @@ -173,7 +173,7 @@ jobs: - name: Publish Container Image to oci.stackable.tech if: ${{ !github.event.pull_request.head.repo.fork }} - uses: stackabletech/actions/publish-image@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/publish-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-registry-uri: oci.stackable.tech image-registry-username: robot$sdp+github-action-build @@ -184,7 +184,7 @@ jobs: - name: Publish Container Image to quay.io if: ${{ !github.event.pull_request.head.repo.fork }} - uses: stackabletech/actions/publish-image@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/publish-image@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-registry-uri: quay.io image-registry-username: stackable+robot_sdp_github_action_build @@ -216,7 +216,7 @@ jobs: - name: Publish and Sign Image Index to oci.stackable.tech id: publish-oci - uses: stackabletech/actions/publish-image-index-manifest@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/publish-image-index-manifest@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-registry-uri: oci.stackable.tech image-registry-username: robot$sdp+github-action-build @@ -226,7 +226,7 @@ jobs: - name: Publish and Sign Image Index to quay.io id: publish-quay - uses: stackabletech/actions/publish-image-index-manifest@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/publish-image-index-manifest@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-registry-uri: quay.io image-registry-username: stackable+robot_sdp_github_action_build @@ -311,7 +311,7 @@ jobs: submodules: recursive - name: Package, Publish, and Sign Helm Chart to oci.stackable.tech - uses: stackabletech/actions/publish-helm-chart@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/publish-helm-chart@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: chart-registry-uri: oci.stackable.tech chart-registry-username: robot$sdp-charts+github-action-build @@ -323,7 +323,7 @@ jobs: publish-and-sign: ${{ !github.event.pull_request.head.repo.fork }} - name: Package, Publish, and Sign Helm Chart to quay.io - uses: stackabletech/actions/publish-helm-chart@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/publish-helm-chart@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: chart-registry-uri: quay.io chart-registry-username: stackable+robot_sdp_charts_github_action_build @@ -354,13 +354,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Run OpenShift Preflight Check for oci.stackable.tech - uses: stackabletech/actions/run-openshift-preflight@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/run-openshift-preflight@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-index-uri: oci.stackable.tech/sdp/${{ env.OPERATOR_NAME }}:${{ needs.build-container-image.outputs.operator-version }} image-architecture: ${{ matrix.arch }} - name: Run OpenShift Preflight Check for quay.io - uses: stackabletech/actions/run-openshift-preflight@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/run-openshift-preflight@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: image-index-uri: quay.io/stackable/sdp/${{ env.OPERATOR_NAME }}:${{ needs.build-container-image.outputs.operator-version }} image-architecture: ${{ matrix.arch }} @@ -402,7 +402,7 @@ jobs: persist-credentials: false - name: Send Notification - uses: stackabletech/actions/send-slack-notification@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/send-slack-notification@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: publish-helm-chart-result: ${{ needs.publish-helm-chart.result }} publish-manifests-result: ${{ needs.publish-index-manifest.result }} diff --git a/template/.github/workflows/integration-test.yml b/template/.github/workflows/integration-test.yml index 18c3e308..6d54cb8e 100644 --- a/template/.github/workflows/integration-test.yml +++ b/template/.github/workflows/integration-test.yml @@ -43,7 +43,7 @@ jobs: # TODO: Enable the scheduled runs which hard-code what profile to use - name: Run Integration Test id: test - uses: stackabletech/actions/run-integration-test@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/run-integration-test@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: replicated-api-token: ${{ secrets.REPLICATED_API_TOKEN }} test-mode-input: ${{ inputs.test-mode-input }} @@ -53,7 +53,7 @@ jobs: - name: Send Notification if: ${{ failure() || github.run_attempt > 1 }} - uses: stackabletech/actions/send-slack-notification@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + uses: stackabletech/actions/send-slack-notification@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: slack-token: ${{ secrets.SLACK_INTEGRATION_TEST_TOKEN }} failed-tests: ${{ steps.test.outputs.failed-tests }} diff --git a/template/.github/workflows/pr_prek.yaml.j2 b/template/.github/workflows/pr_prek.yaml.j2 index f8b2d973..172ea7e4 100644 --- a/template/.github/workflows/pr_prek.yaml.j2 +++ b/template/.github/workflows/pr_prek.yaml.j2 @@ -28,7 +28,7 @@ jobs: persist-credentials: false submodules: recursive fetch-depth: 0 - - uses: stackabletech/actions/run-prek@a14cbd08d9e034e2361ea9205b32aff0491885db # v0.15.0 + - uses: stackabletech/actions/run-prek@a8af17a19bdcc3b5da0065f76e73827ba0c072ce # v0.16.0 with: rust: ${{ env.RUST_TOOLCHAIN_VERSION }} hadolint: ${{ env.HADOLINT_VERSION }}