This topic explains how to integrate GitHub Actions build attestations with JFrog's Evidence service to create a secure, verifiable audit trail for your software artifacts.
The idea is to create a secure and traceable link from your source code to the final build artifact.
Generate Attestation in GitHub Actions: You use the
actions/attest-build-provenanceaction in your workflow to create a cryptographically signed attestation. This attestation follows the SLSA and in-toto frameworks, providing verifiable proof of where and how your artifact was built.Push to JFrog Artifactory: Your workflow pushes the built artifact (for example, a Docker image, a binary) to JFrog Artifactory.
Ingest into JFrog Evidence: The integration automatically ingests the build attestation from GitHub into JFrog Evidence. It intelligently links this attestation to the specific artifact stored in Artifactory.
By integrating them, you ensure that every artifact in Artifactory has a verifiable history, which is crucial for security, compliance, and auditing. Attestations of build provenance that you generate with the GitHub Action can be automatically sent to and stored within JFrog Evidence.
Sample Workflow
Code Push: A developer pushes code to your GitHub repository.
Build Trigger: A GitHub Actions workflow starts.
Build and Push Artifact: The workflow builds your artifact (for example, a Docker image) and pushes it to a repository in JFrog Artifactory.
Generate and Store Evidence: The
attest-build-provenanceaction generates the signed attestation. Because of the native integration (which occurs in the postjfrog/setup-jfrog-clistep), this attestation is automatically sent to your JFrog Platform and stored as evidence linked directly to the newly pushed artifact.
Ensure your workflow has the correct permissions to write attestations and use OIDC.
# This workflow demonstrates building a Docker image, pushing it to JFrog Artifactory,
# and attaching an SLSA build provenance attestation, which is stored in JFrog Evidence.
name: Build, Push, and Attest to JFrog
on:
push:
branches:
- main
workflow_dispatch:
# Use GitHub variables (vars) and secrets (secrets) for configuration
env:
JF_REGISTRY: ${{ vars.JF_REGISTRY }}
JF_DOCKER_REPO: ${{ vars.JF_DOCKER_REPO }}
IMAGE_NAME: ${{ vars.IMAGE_NAME }}
jobs:
build-and-attest:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write # Required for OIDC token access
attestations: write # Required for attestation
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Install and Configure JFrog CLI
id: setup-jfrog-cli
uses: jfrog/setup-jfrog-cli@4.6.1
env:
JF_URL: ${{ secrets.JF_URL }}
with:
# Replace with the name of your configured OIDC provider in JFrog
oidc-provider-name: 'your-github-oidc-provider-name'
- name: Log in to JFrog Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ env.JF_REGISTRY }}
username: ${{ steps.setup-jfrog-cli.outputs.oidc-user }}
password: ${{ steps.setup-jfrog-cli.outputs.oidc-token }}
- name: Build and Push Docker Image
id: build-and-push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ env.JF_REGISTRY }}/${{ env.JF_DOCKER_REPO }}/${{ env.IMAGE_NAME }}:${{ github.run_number }}
- name: Attest Docker Image and Send to JFrog Evidence
uses: actions/attest-build-provenance@v3
with:
# The 'oci://' prefix is required by JFrog to correctly parse the artifact type
subject-name: oci://${{ env.JF_REGISTRY }}/${{ env.JF_DOCKER_REPO }}/${{ env.IMAGE_NAME }}
# This links the attestation directly to the image digest from the build step
subject-digest: ${{ steps.build-and-push.outputs.digest }}