diff --git a/.github/workflows/shared-publish-java-to-docker-versioned.yaml b/.github/workflows/shared-publish-java-to-docker-versioned.yaml index 36bad1ec..ee148820 100644 --- a/.github/workflows/shared-publish-java-to-docker-versioned.yaml +++ b/.github/workflows/shared-publish-java-to-docker-versioned.yaml @@ -66,6 +66,8 @@ jobs: security-events: write packages: write pull-requests: write + id-token: write + attestations: write outputs: jar_version: ${{ steps.version.outputs.new_version }} image_tag: ${{ steps.updatePom.outputs.image_tag }} @@ -203,6 +205,7 @@ jobs: scan_type: image - name: Push to Docker + id: push uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: context: ${{inputs.working_dir}} @@ -213,6 +216,13 @@ jobs: JAR_VERSION=${{ steps.version.outputs.new_version }} IMAGE_VERSION=${{ steps.version.outputs.new_version }} + - name: Attest build provenance + if: ${{ steps.checkRelease.outputs.not_snapshot == 'true' }} + uses: IABTechLab/uid2-shared-actions/actions/attest_image@v3 + with: + subject_name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}${{ inputs.append_image_name }} + subject_digest: ${{ steps.push.outputs.digest }} + - name: Build Changelog id: github_release if: ${{ steps.checkRelease.outputs.is_release == 'true' }} diff --git a/.github/workflows/shared-publish-to-docker-versioned.yaml b/.github/workflows/shared-publish-to-docker-versioned.yaml index 942b4953..18e88698 100644 --- a/.github/workflows/shared-publish-to-docker-versioned.yaml +++ b/.github/workflows/shared-publish-to-docker-versioned.yaml @@ -51,6 +51,8 @@ jobs: security-events: write packages: write pull-requests: write + id-token: write + attestations: write steps: - name: Setup id: setup diff --git a/actions/attest_image/action.yaml b/actions/attest_image/action.yaml new file mode 100644 index 00000000..f76de7b8 --- /dev/null +++ b/actions/attest_image/action.yaml @@ -0,0 +1,49 @@ +name: Attest container image +description: | + Generates a SLSA build-provenance attestation for an OCI image, pushes the + signed bundle to the registry alongside the image, and verifies it via + `gh attestation verify` so a misconfigured signature fails the build rather + than the consumer pull. + + actions/attest already lowercases subject-name when push-to-registry is true + (see github.com/actions/attest src/main.ts and src/subject.ts), but + `gh attestation verify` does not lowercase the OCI URI we pass to it. To + keep the signed name and the verified URI byte-identical, we lowercase + once here and reuse the value in both steps. + +inputs: + subject_name: + description: Fully qualified image reference (registry/owner/repo[+suffix]). Mixed case is fine — this action lowercases it for OCI compliance. + required: true + subject_digest: + description: OCI manifest digest (sha256:...) emitted by docker/build-push-action. + required: true + +runs: + using: composite + steps: + - name: Lowercase image reference + id: ref + shell: bash + run: | + value="$(printf '%s' '${{ inputs.subject_name }}' | tr '[:upper:]' '[:lower:]')" + echo "value=${value}" >> "$GITHUB_OUTPUT" + + - name: Attest build provenance + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 + env: + # Mirrors actions/attest-build-provenance, prevents oversized OCI registry auth-challenge headers triggering HPE_HEADER_OVERFLOW. + NODE_OPTIONS: --max-http-header-size=32768 + with: + subject-name: ${{ steps.ref.outputs.value }} + subject-digest: ${{ inputs.subject_digest }} + push-to-registry: true + + - name: Verify attestation + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + gh attestation verify \ + "oci://${{ steps.ref.outputs.value }}@${{ inputs.subject_digest }}" \ + --owner "${{ github.repository_owner }}" diff --git a/actions/shared_publish_to_docker/action.yaml b/actions/shared_publish_to_docker/action.yaml index 295ee6d9..096acd5f 100644 --- a/actions/shared_publish_to_docker/action.yaml +++ b/actions/shared_publish_to_docker/action.yaml @@ -90,6 +90,7 @@ runs: scan_type: ${{ inputs.scan_type }} - name: Push to Docker + id: push uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5 with: context: ${{ inputs.docker_context }} @@ -100,3 +101,10 @@ runs: build-args: | JAR_VERSION=${{ inputs.new_version }} IMAGE_VERSION=${{ inputs.new_version }} + + - name: Attest build provenance + if: ${{ inputs.not_snapshot == 'true' }} + uses: IABTechLab/uid2-shared-actions/actions/attest_image@v3 + with: + subject_name: ${{ inputs.docker_registry }}/${{ inputs.docker_image_name }} + subject_digest: ${{ steps.push.outputs.digest }}