From d1220ccbae7b8cc20d0919cf284787862b716a51 Mon Sep 17 00:00:00 2001 From: Balasubramanyam Kosuri Date: Mon, 7 Jul 2025 09:00:12 +0530 Subject: [PATCH] Updated README.md --- README.md | 259 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 165 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 7d62dc4..9170e99 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,100 @@ -# Attach Evidence in Artifactory -Artifactory enables you to attach evidence (signed metadata) to a designated subject, such as an artifact, build, package, or Release Bundle v2. These evidence files provide a record of an external process performed on the subject, such as test results, vulnerability scans, or official approval. +# **Attach Evidence in Artifactory** -This document describes how to use the JFrog CLI to create different types of evidence related to a Docker image deployed to Artifactory, including: +This repository provides a comprehensive, hands-on example of how to create and attach signed evidence to your software assets at every stage of the development lifecycle using **JFrog Artifactory** and **JFrog CLI**. -* Package evidence -* Generic evidence -* Build evidence -* Release Bundle evidence +By following this guide, you will learn how to build a verifiable, auditable trail for your software, from a single artifact to an immutable Release Bundle. This is a foundational practice for securing your software supply chain and enabling automated, policy-driven governance. -The following workflow is described: +### **What You'll Accomplish** -1. [Bootstrapping](#bootstrapping) - 1. [Install JFrog CLI](#install-jfrog-cli) - 2. [Log In to the Artifactory Docker Registry](#log-in-to-the-artifactory-docker-registry) -2. [Build the Docker Image](#build-the-docker-image) -3. [Attach Package Evidence](#attach-package-evidence) -4. [Upload README File and Associated Evidence](#upload-readme-file-and-associated-evidence) -5. [Publish Build Info and Attach Build Evidence](#publish-build-info-and-attach-build-evidence) -6. [Create a Release Bundle v2 from the Build](#create-a-release-bundle-v2-from-the-build) -7. [Attach Release Bundle Evidence](#attach-release-bundle-evidence) -8. [Create an External Policy to Potentially Block Release Bundle Promotion](#create-an-external-policy-to-potentially-block-release-bundle-promotion) +* **Build and Publish** a multi-platform Docker image. +* **Attach Signed Evidence** to four distinct types of subjects: + 1. A **Generic Artifact** (a README.md file). + 2. A **Software Package** (eg: a Docker image, npm, go,…etc). + 3. A **Build Info** object (the CI build record). + 4. An immutable **Release Bundle v2**. +* **Understand the "Why"**: Learn how this chain of evidence enables secure, policy-based promotions. -Refer to [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) for the complete script. +### **The Evidence Journey:** -*** +The GitHub Actions workflow (.github/workflows/build.yml) performs a sequence of operations to build a chain of trust. Evidence is attached at each critical step. -## Note +### **Note** -For more information about evidence on the JFrog platform, see Evidence Management. -*** +For more information about evidence on the JFrog platform, see [Evidence Management]([https://github.com/jfrog/Evidence-Examples/blob/main/README.md#bootstrapping](https://jfrog.com/help/r/jfrog-artifactory-documentation/evidence-management)). -## Prerequisites +```mermaid +graph TD + subgraph "1. Build & Initial Evidence" + A[Start] --> B(Build & Push Docker Image); + B --> C{Attach Evidence to Package}; + D[Upload README.md] --> E{Attach Evidence to Generic File}; + end -* Make sure JFrog CLI 2.65.0 or above is installed and in your system PATH. For installation instructions, see [Install JFrog CLI](#bootstrapping). + subgraph "2. Aggregate into a Build" + C --> F(Publish Build Info); + E --> F; + F --> G{Attach Evidence to Build}; + end + + subgraph "3. Create Immutable Release" + G --> H(Create Release Bundle v2 from Build); + H --> I{Attach Evidence to Release Bundle}; + end + + subgraph "4. Enable Governance" + I --> J[Ready for Secure Promotion with Policy Checks]; + + end +``` + + +### **Getting Started: Prerequisites & Configuration** + +Before running the workflow, please ensure you have the following set up. + +## **Prerequisites** + +* Make sure JFrog CLI 2.65.0 or above is installed and in your system PATH. For installation instructions, see [Install JFrog CLI](https://github.com/jfrog/Evidence-Examples/blob/main/README.md#bootstrapping). * Make sure Artifactory can be used as a Docker registry. Please refer to [Getting Started with Artifactory as a Docker Registry](https://www.jfrog.com/confluence/display/JFROG/Getting+Started+with+Artifactory+as+a+Docker+Registry) in the JFrog Artifactory User Guide. You should end up with a Docker registry URL, which is mapped to a local Docker repository (or a virtual Docker repository with a local deployment target) in Artifactory. You'll need to know the name of the Docker repository to later collect the published image build-info. * Make sure the following repository variables are configured in GitHub settings: - * ARTIFACTORY_URL (location of your Artifactory installation) - * BUILD_NAME (planned name for the build of the Docker image) - * BUNDLE_NAME (planned name for the Release Bundle created from the build) + * ARTIFACTORY\_URL (location of your Artifactory installation) + * BUILD\_NAME (planned name for the build of the Docker image) + * BUNDLE\_NAME (planned name for the Release Bundle created from the build) * Make sure the following repository secrets are configured in GitHub settings: - * ARTIFACTORY_ACCESS_TOKEN (access token used for authentication) - * JF_USER (your username in Artifactory) - * PRIVATE_KEY (the key used to sign evidence) + * ARTIFACTORY\_ACCESS\_TOKEN (access token used for authentication) + * JF\_USER (your username in Artifactory) + * PRIVATE\_KEY (the key used to sign evidence) + +**GitHub Secrets** + +| Secret Name | Description | Example Value | +| :---- | :---- | :---- | +| ARTIFACTORY\_ACCESS\_TOKEN | A valid JFrog Access Token with permissions to deploy and annotate. | | +| JF\_USER | Your JFrog Platform username, used for the docker login action. | my-user | +| PRIVATE\_KEY | The raw private key used to sign all evidence created in the workflow. | \-----BEGIN PRIVATE KEY-----... | + +**GitHub Variables** + +| Variable Name | Description | Example Value | +| :---- | :---- | :---- | +| ARTIFACTORY\_URL | The base URL of your JFrog Platform instance. | https://mycompany.jfrog.io | +| BUILD\_NAME | A unique name for the build information in Artifactory. | evidence-example-build | +| BUNDLE\_NAME | The name of the Release Bundle that will be created. | evidence-example-bundle | +--- +### **The Evidence Journey: Step-by-Step** -## Bootstrapping +This workflow demonstrates how evidence adds value at different levels of abstraction. For the complete implementation, please refer to the [build.yml workflow file](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml). -### Install JFrog CLI +#### **Install JFrog CLI** -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) installs the latest version of the JFrog CLI and performs checkout. Please note that a valid access token is required. +This step uses the `jfrog/setup-jfrog-cli` action to install the JFrog CLI into the GitHub Actions runner and configures it with your Artifactory URL and access token. -```yaml + + +``` jobs: Docker-build-with-evidence: runs-on: ubuntu-latest @@ -66,11 +108,13 @@ jobs: - uses: actions/checkout@v4 ``` -### Log In to the Artifactory Docker Registry +#### **Log In to the Artifactory Docker Registry** + +Here, we securely log in to the Artifactory Docker registry. This step also sets up QEMU and Docker Buildx, which are required to build multi-platform Docker images (e.g., for `linux/amd64` and `linux/arm64`). + -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) logs into the Docker registry, as described in the [prerequisites](#prerequisites), and sets up QEMU and Docker Buildx in preparation for building the Docker image. -```yaml +``` - name: Log in to Artifactory Docker Registry uses: docker/login-action@v3 with: @@ -88,106 +132,133 @@ This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main install: true ``` -## Build the Docker Image +--- + +### **Build the Docker Image** + +This step builds a multi-platform Docker image using the provided `Dockerfile` and pushes it to your Artifactory repository. The `jfrog rt build-docker-create` command captures the image details and associates them with a build name and number, laying the groundwork for creating build information. -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) builds the Docker image and deploys it to Artifactory. -```yaml + +``` - name: Build Docker image - run: | - URL=$(echo ${{ vars.ARTIFACTORY_URL }} | sed 's|^https://||') - REPO_URL=${URL}'/example-project-docker-dev-virtual' - docker build --build-arg REPO_URL=${REPO_URL} -f Dockerfile . \ - --tag ${REPO_URL}/example-project-app:${{ github.run_number }} \ - --output=type=image --platform linux/amd64 --metadata-file=build-metadata --push + run: | + URL=$(echo ${{ vars.ARTIFACTORY_URL }} | sed 's|^https://||') + REPO_URL=${URL}'/example-project-docker-dev-virtual' + docker build --build-arg REPO_URL=${REPO_URL} -f Dockerfile . \ + --tag ${REPO_URL}/example-project-app:${{ github.run_number }} \ + --output=type=image --platform linux/amd64 --metadata-file=build-metadata --push jfrog rt build-docker-create example-project-docker-dev --image-file build-metadata --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }} ``` -## Attach Package Evidence +--- -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) creates evidence for the package containing the Docker image. The evidence is signed with your private key, as defined in the [Prerequisites](#prerequisites). +### **Attach Package Evidence** -```yaml +Now we attach the first piece of evidence directly to the Docker image **package**. This signed evidence acts as a verifiable record, attesting that a specific action (like a signature from a CI process) was performed on this package version. + + + +``` - name: Evidence on docker - run: | - echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > sign.json - jf evd create --package-name example-project-app --package-version 32 --package-repo-name example-project-docker-dev \ - --key "${{ secrets.PRIVATE_KEY }}" \ - --predicate ./sign.json --predicate-type https://jfrog.com/evidence/signature/v1 - echo ' Evidence attached: `signature` ' + run: | + echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > sign.json + jf evd create --package-name example-project-app --package-version 32 --package-repo-name example-project-docker-dev \ + --key "${{ secrets.PRIVATE_KEY }}" \ + --predicate ./sign.json --predicate-type https://jfrog.com/evidence/signature/v1 + echo ' Evidence attached: `signature` ' ``` -## Upload README File and Associated Evidence +--- -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) uploads the README file and creates signed evidence about this generic artifact. The purpose of this section is to demonstrate the ability to create evidence for any type of file uploaded to Artifactory, in addition to packages, builds, and Release Bundles. +### **Upload README File and Associated Evidence** -```yaml +To demonstrate that evidence can be attached to *any* artifact, not just packages, this step uploads the `README.md` file to a generic repository and attaches similar signed evidence to it. + + + +``` - name: Upload readme file - run: | - jf rt upload ./README.md example-project-generic-dev/readme/${{ github.run\_number }}/ --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }} - jf evd create --subject-repo-path example-project-generic-dev/readme/${{ github.run_number }}/README.md \ - --key "${{ secrets.PRIVATE_KEY }}" \ + run: | + jf rt upload ./README.md example-project-generic-dev/readme/${{ github.run_number }}/ --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }} + jf evd create --subject-repo-path example-project-generic-dev/readme/${{ github.run_number }}/README.md \ + --key "${{ secrets.PRIVATE_KEY }}" \ --predicate ./sign.json --predicate-type https://jfrog.com/evidence/signature/v1 ``` -## Publish Build Info and Attach Build Evidence +--- + +### **Publish Build Info and Attach Build Evidence** -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) creates a build from the package containing the Docker image and then creates signed evidence attesting to its creation. +This step aggregates all the artifacts and metadata captured so far (the Docker image and the README) into a comprehensive **Build Info** object in Artifactory. Immediately after, it attaches signed evidence to this entire build, attesting to the integrity of the build process itself. -```yaml + + +``` - name: Publish build info run: jfrog rt build-publish ${{ vars.BUILD_NAME }} ${{ github.run_number }} - name: Sign build evidence - run: | - echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > sign.json + run: | + echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > sign.json jf evd create --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }} \ --predicate ./sign.json --predicate-type https://jfrog.com/evidence/build-signature/v1 \ - --key "${{ secrets.PRIVATE_KEY }}" + --key "${{ secrets.PRIVATE_KEY }}" echo ' Evidence attached: `build-signature` ' >> $GITHUB_STEP_SUMMARY ``` -## Create a Release Bundle v2 from the Build +--- + +### **Create a Release Bundle v2 from the Build** + +The workflow now creates an immutable **Release Bundle** from the build we just published. This bundle is a tamper-proof, versioned collection that is ideal for promoting through your SDLC stages. -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) creates an immutable Release Bundle v2 from the build containing the Docker image. Having a Release Bundle prevents any changes to the Docker image as it progresses through the various stages of your SDLC towards eventual distribution to your end users. -```yaml + +``` - name: Create release bundle - run: | - echo '{ "files": [ {"build": "'"${{ vars.BUILD_NAME }}/${{ github.run_number }}"'" } ] }' > bundle-spec.json - jf release-bundle-create ${{ vars.BUNDLE_NAME }} ${{ github.run_number }} --signing-key PGP-RSA-2048 --spec bundle-spec.json --sync=true - NAME_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&repositoryKey=example-project-release-bundles-v2&activeKanbanTab=promotion' - VER_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&releaseBundleVersion='${{ github.run_number }}'&repositoryKey=example-project-release-bundles-v2&activeVersionTab=Version%20Timeline&activeKanbanTab=promotion' + run: | + echo '{ "files": [ {"build": "'"${{ vars.BUILD_NAME }}/${{ github.run_number }}"'" } ] }' > bundle-spec.json + jf release-bundle-create ${{ vars.BUNDLE_NAME }} ${{ github.run_number }} --signing-key PGP-RSA-2048 --spec bundle-spec.json --sync=true + NAME_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&repositoryKey=example-project-release-bundles-v2&activeKanbanTab=promotion' + VER_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&releaseBundleVersion='${{ github.run_number }}'&repositoryKey=example-project-release-bundles-v2&activeVersionTab=Version%20Timeline&activeKanbanTab=promotion' echo ' Release bundle ['${{ vars.BUNDLE_NAME }}']('${NAME_LINK}'):['${{ github.run_number }}']('${VER_LINK}') created' >> $GITHUB_STEP_SUMMARY ``` -*** +--- -**Note** +### **Attach Release Bundle Evidence** -For more information about using the JFrog CLI to create a Release Bundle, see [https://docs.jfrog-applications.jfrog.io/jfrog-applications/jfrog-cli/cli-for-jfrog-artifactory/release-lifecycle-management](https://docs.jfrog-applications.jfrog.io/jfrog-applications/jfrog-cli/cli-for-jfrog-artifactory/release-lifecycle-management). -*** +Finally, we attach signed evidence to the immutable Release Bundle itself. This could represent a successful integration test or final approval, providing a verifiable gate for promotion to production environments. -## Attach Release Bundle Evidence -This section of [build.yml](https://github.com/jfrog/Evidence-Examples/tree/main/.github/workflows/build.yml) creates signed evidence about the Release Bundle. -```yaml +``` - name: Evidence on release-bundle v2 - run: | - echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > rbv2_evidence.json - JF_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&releaseBundleVersion='${{ github.run_number }}'&repositoryKey=release-bundles-v2&activeVersionTab=Version%20Timeline&activeKanbanTab=promotion' - echo 'Test on Release bundle ['${{ vars.BUNDLE_NAME }}':'${{ github.run_number }}']('${JF_LINK}') success' >> $GITHUB_STEP_SUMMARY - jf evd create --release-bundle ${{ vars.BUNDLE_NAME }} --release-bundle-version ${{ github.run_number }} \ - --predicate ./rbv2_evidence.json --predicate-type https://jfrog.com/evidence/rbv2-signature/v1 \ - --key "${{ secrets.PRIVATE_KEY }}" + run: | + echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > rbv2_evidence.json + JF_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&releaseBundleVersion='${{ github.run_number }}'&repositoryKey=release-bundles-v2&activeVersionTab=Version%20Timeline&activeKanbanTab=promotion' + echo 'Test on Release bundle ['${{ vars.BUNDLE_NAME }}':'${{ github.run_number }}']('${JF_LINK}') success' >> $GITHUB_STEP_SUMMARY + jf evd create --release-bundle ${{ vars.BUNDLE_NAME }} --release-bundle-version ${{ github.run_number }} \ + --predicate ./rbv2_evidence.json --predicate-type https://jfrog.com/evidence/rbv2-signature/v1 \ + --key "${{ secrets.PRIVATE_KEY }}" echo ' Evidence attached: integration-test ' >> $GITHUB_STEP_SUMMARY ``` -## Create an External Policy to Potentially Block Release Bundle Promotion +--- + +### **Create an External Policy to Potentially Block Release Bundle Promotion** When the Evidence service is used in conjunction with JFrog Xray, each Release Bundle promotion generates evidence in the form of a CycloneDX SBOM. You can create a policy in an external tool (for example, a rego policy) that reviews the contents of the CycloneDX evidence file and decides whether to block the promotion (because the Release Bundle fails to meet all your organization's requirements for promotion to the next stage of your SDLC). -To see a sample rego policy, go [here](https://github.com/jfrog/Evidence-Examples/blob/main/policy/policy.rego). -For more information about integrating Release Lifecycle Management and Evidence with Xray, see [Scan Release Bundles (v2) with Xray](https://jfrog.com/help/r/jfrog-artifactory-documentation/scan-release-bundles-v2-with-xray). +To see a sample rego policy, go [here](https://github.com/jfrog/Evidence-Examples/blob/main/policy/policy.rego). For more information about integrating Release Lifecycle Management and Evidence with Xray, see [Scan Release Bundles (v2) with Xray](https://jfrog.com/help/r/jfrog-artifactory-documentation/scan-release-bundles-v2-with-xray). + +### **References** +* **Product Documentation:** + * [Evidence Management Overview](https://jfrog.com/help/r/jfrog-artifactory-documentation/evidence-management) + * [Getting Started with Artifactory as a Docker Registry](https://www.jfrog.com/confluence/display/JFROG/Getting+Started+with+Artifactory+as+a+Docker+Registry) + * [Scan Release Bundles (v2) with Xray](https://jfrog.com/help/r/jfrog-artifactory-documentation/scan-release-bundles-v2-with-xray) +* **JFrog CLI Documentation:** + * [JFrog CLI Command Reference](https://www.google.com/search?q=https://jfrog.com/help/r/jfrog-cli/jfrog-cli-command-reference) + * [Release Lifecycle Management with CLI](https://www.google.com/search?q=https://jfrog.com/help/r/jfrog-cli/release-lifecycle-management)