Create Evidence using REST APIs

JFrog Artifactory Documentation

Products
JFrog Artifactory
Content Type
User Guide

JFrog offers a set of REST APIs to create and deploy evidence to Artifactory, as an alternative to using the JFrog CLI. These APIs are especially useful when integrating a third-party tool with the JFrog platform for the purpose of creating and deploying evidence to JFrog. The basic workflow is as follows:

  1. Prepare the Predicate – Prepare a JSON file containing relevant metadata about the evidence subject.

  2. Run the Prepare Evidence API – Use the Prepare Evidence API to create the evidence payload and deployment URL.

  3. Sign the Payload – Sign the payload returned by the Prepare Evidence API.

  4. Build the DSSE – Build the DSSE, which is the standard envelope required by the platform to deploy evidence.

  5. Create and Deploy the Evidence – Use the Deploy Evidence API to create and deploy the evidence.

Note

The examples shown in this section are based on a GitHub Actions workflow. However, the Bash commands contained in the workflow can be adapted for other Linux-based environments where the use of the JFrog CLI is not an option.

Prerequisites

Before starting the process, make sure to prepare the following:

Prepare the Predicate

The predicate is a user-defined JSON file containing metadata about the evidence subject. In other words, the predicate contains the actual contents of the evidence. The user defines the contents and format of the JSON file, but they are typically defined by the predicate type. Here is a very simple example of a predicate:

{
	"builder": {
		"id": "uri:github-actions"
	},
	"runId": {
		"workflow_run_id": "17540367721"
	}
}

Run the Prepare Evidence API

The Prepare Evidence API contains the predicate, the predicate type, and a definition of the evidence subject (for example, the artifact or build associated with the evidence). You can optionally add a markdown version of the predicate for easy readability in the platform UI, and the provider ID, which indicates the source of the evidence (for example, Sonar or GitHub).Prepare Evidence

The API returns the following elements that help you prepare for evidence creation and deployment:

  • Post URL: This is the URL you will use when calling the Deploy Evidence API.

  • DSSE payload: This is the evidence payload you will use to construct the DSSE, which is the envelope containing the signed evidence to be deployed to the JFrog platform. The payload is encoded using Base64 encoding.

  • DSSE payload type: This is a field that you will use in the DSSE.

  • Pre-Authentication Encoding (PAE) statement: The PAE statement is used by DSSE as a standardized format for signing the payload.

REQUEST=$(cat << EOF
  {
    "subject": {
      "subject_type": "package",
      "package_repo": "commons-dev-maven-local",
      "package_name": "com.example:quote-of-day-service",
      "package_version": "1.0.0"
    },
    "predicate": {
      "statement": "This maven package is great."
    },
    "predicate_type": "https://example.com/evidence/statement/v1",
    "markdown": "# Example Statement\n\n## Statement\n\nThis maven package is great."
  }
  EOF
  )
  echo "Request: $REQUEST"
  URL="${{ vars.ARTIFACTORY_URL }}/evidence/api/v1/evidence/prepare"
  echo "URL: $URL"
  [ "${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}" == "" ] && echo "secrets.ARTIFACTORY_ACCESS_TOKEN is empty!" && exit 1
  curl -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}" -d "$REQUEST" -o response.json "$URL"
  echo "Response: $(cat response.json)"
  # Make sure it is valid response
  cat response.json | grep "dsse_payload"

Sign the Payload

This stage of the process includes the following steps:

  1. Decoding the Base64 payload returned by the Prepare Evidence API. The payload must be decoded before it is signed.

  2. Creating the Pre-Authentication Encoding (PAE) statement, which in DSSE is what is actually signed (as opposed to signing the payload directly). The PAE statement is constructed from a set prefix, the length of the payload type, the payload type, the length of the payload, and the payload.

    Important

    This step is not required if you set the query parameter include_pae=true in the Prepare Evidence API.

  3. Signing the payload.

When the PAE was already created by the Prepare Evidence API:

PRE_AUTH_ENC=$(cat response.json | jq -r .pre_authentication_encoding)
echo "Pre-authentication encoding: $PRE_AUTH_ENC"
echo -n "${{ secrets.JIRA_TEST_PKEY }}" > key_file
PAYLOAD_SIGNATURE=$(echo -n "$PRE_AUTH_ENC" | openssl dgst -sha256 -sign key_file | openssl base64 | tr -d '\n')
[ "$?" != "0" -o "$PAYLOAD_SIGNATURE" == "" ] && rm key_file && echo "Failed to create signature." && exit 1
rm key_file
echo "Signature: $PAYLOAD_SIGNATURE"
echo -n "$PAYLOAD_SIGNATURE" > signature_file

When creating the PAE manually:

BASE64_PAYLOAD=$(cat response.json | jq -r .dsse_payload)
  echo "Base64 payload: $BASE64_PAYLOAD"
  PAYLOAD=$(echo -n "$BASE64_PAYLOAD" | base64 -d)
  echo "Payload: $PAYLOAD"
  PAYLOAD_TYPE=$(cat response.json | jq -r .dsse_payload_type)
  echo "Payload type: $PAYLOAD_TYPE"
  PAYLOAD_LEN="${#PAYLOAD}"
  PAYLOAD_TYPE_LEN="${#PAYLOAD_TYPE}"
  PRE_AUTH_ENC="DSSEv1 $PAYLOAD_TYPE_LEN $PAYLOAD_TYPE $PAYLOAD_LEN $PAYLOAD"
  echo "Pre-authentication encoding: $PRE_AUTH_ENC"
  echo -n "${{ secrets.JIRA_TEST_PKEY }}" > key_file
  PAYLOAD_SIGNATURE=$(echo -n "$PRE_AUTH_ENC" | openssl dgst -sha256 -sign key_file | openssl base64 | tr -d '\n')
  [ "$?" != "0" -o "$PAYLOAD_SIGNATURE" == "" ] && echo "Failed to create signature." && exit 1
  rm key_file
  echo "Signature: $PAYLOAD_SIGNATURE"
  echo -n "$PAYLOAD_SIGNATURE" > signature_file

Build the DSSE

DSSE is the standard JSON format used by the JFrog platform for evidence creation. The JSON file contains:

  • payloadType: Use the dsse_payload_type returned by the Prepare Evidence API.

  • payload: Use the Base64-encoded dsse_payload returned by the Prepare Evidence API.

  • signatures: Use the Base64-encoded signature generated when you signed the payload and the keyid, which is the alias for the public key. If this public key is stored in Artifactory, any evidence created with the private key will be verified using this public key.

Note

When creating evidence using the REST APIs, JFrog supports both the RS256 algorithm (with PKCS#1 v.1.5 padding) and the PS256 algorithm (with PSS padding). If you create the signature using PS256, you must specify this algorithm as metadata (case-sensitive) when defining the keyid, as follows:

"keyid": "{public_key_name};PS256",

DSSE=$(cat << EOF
  {
    "payloadType": $(cat response.json | jq .dsse_payload_type),
    "payload": $(cat response.json | jq .dsse_payload),
    "signatures": [
      {
        "keyid": "${{ vars.JIRA_TEST_KEY }}",
        "sig": "$(cat signature_file)"
      }
    ]
  }
  EOF
  )
  echo "DSSE: $DSSE"
  echo -n "$DSSE" > dsse.json

For more information, see Evidence Envelope.

Tip

Use JFrog's DSSE Attestation Online Decoder Tool (located at https://dsse.io/) to decode and verify the payload. For more information, see How to Use the DSSE Attestation Online Decoder Tool.

Create and Deploy the Evidence

In the final step, use the Deploy Evidence API to create the evidence and deploy it to the defined evidence subject in Artifactory. The POST URL is constructed from the URL of your JFrog platform installation plus the payload URL returned by the Prepare Evidence API.Deploy Evidence

POST_URL=$(cat response.json | jq -r .post_url)
  echo "POST_URL: $POST_URL"
  URL="${{ vars.ARTIFACTORY_URL }}$POST_URL"
  echo "URL: $URL"
  BODY=$(cat dsse.json)
  echo "BODY: $BODY"
  echo 
  echo
  curl -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}" -d "$BODY" "$URL"
  [ $? -ne 0 ] && echo "Failed to create evidece." && exit 1
  echo
  echo "Created evidence successfully :-)"