Skip to main content

Azure Pipelines

Cimon Attest Task

The best method to run Cimon Attest in Azure Pipelines is through the dedicated extension that allows generating and attesting your provenance seamlessly within any Azure Pipelines build. The extension can be found at the official Visual Studio Marketplace here.

The extension is currently supported only for Ubuntu-based hosted runners:

  • vmImage: 'ubuntu-latest'
  • vmImage: 'ubuntu-22.04'
  • vmImage: 'ubuntu-20.04'

Installation

Prerequisites

Before installing the Azure Pipelines Extension, ensure that you have the following prerequisites:

  • An Azure DevOps organization with sufficient permissions to install extensions.
  • Access to the Azure Pipelines service in your organization.

Install Azure Pipelines Extension

To install the Cimon Extension in your organization, follow these steps:

  • Select the organization where you want to install the extension and click Install.

  • Wait for the installation to complete. Once installed, you will see a success message.

Example Usage

Once the extension is installed, you may edit the desired Azure Pipeline workflow and add the CimonAttest@0 task once created the desired artifacts. You can attest for any artifact, as long as they have a unique SHA256 digest.

The following Azure Pipelines workflow simulates how to generate provenance for specified hashes of dist/artifact1 and dist/artifact2.

The workflow has the following steps:

  1. Build artifacts: This step simulates a process in which artifacts are created before the CimonAttest@0 invocation. The artifacts could be of any kind - .jar, .war, .whl, .dll, .exe, etc. In the example, we generate two stub artifacts.
  2. Generate sign key: This step creates a private key that will be used for the signature process. It could be substituted for any other key in the PEM format of the supported keys (see more on supported format here. This step is optional.
  3. CimonAttest task: This step uses the CimonAttest task, the subject's input, and the signature key (if provided) to generate SLSA provenance by extracting the relevant information from the build and signing it.
trigger:
- main

pool:
vmImage: ubuntu-latest

steps:
- script: |
mkdir dist
echo artifact123 > dist/artifact1
echo artifact321 > dist/artifact2
displayName: Build artifacts

- script: |
openssl genrsa -out private-key.pem 3072
displayName: Generate sign key

- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: |
dist/artifact1
dist/artifact2
signKey: private-key.pem

More examples could be found in the examples page.

Cimon Attest Parameters

NameDefault
clientIdCimon client ID for authentication
secretCimon secret for authentication
urlCimon endpoint for authentication
subjectsA white space seperated list of paths, or base64-encoded subjects. Each path can be file, directory or image reference
imageRef(deprecated) The container reference to generate provenance for. Either subjects or imageRef are required
signKeyInput path to a private ECDSA/RSA/ED25519 key used to sign provenance statement. Can be an absolute path or a relative path to the working directory
provenanceOutputprovenance.intoto.jsonlProvenance output path. Can be an absolute path or a relative path to the working directory
signedProvenanceOutputprovenance.intoto.jsonl.sigSigned provenance output path. Can be an absolute path or a relative path to the working directory
reportJobSummarytrueEnable to report the provenance documents as job summary output
reportArtifacttrueEnable to report the provenance documents as job artifacts
logLevelinfoLog level (Used for debugging)
failOnErrorfalseFail the CI if Cimon encountered an error
releasePathPath to Cimon release file (Used for debugging)

Cimon Attest Output

Cimon Attest task provides output information that can be used when task execution is over: In the example, we use two output variables of the CimonAttest task:

  • provenanceOutput - Path to a file that contains provenance output. It should exist if the task succeeded.
  • signedProvenanceOutput - Path to a file that contains signed provenance output. It should exist if the task succeeded and was given a signing key.
steps:
- task: CimonAttest@0
inputs: ...
name: cimonAttest

# provenanceOutput is the path to the provenance output file
- script: |
cat $(cimonAttest.provenanceOutput) | jq
condition: ne(variables['cimonAttest.provenanceOutput'], '')
displayName: Print provenance

# signedProvenanceOutput is the path to the signed provenance output file
# relevant only if signature keys were given.
- script: |
cat $(cimonAttest.signedProvenanceOutput) | jq
condition: ne(variables['cimonAttest.signedProvenanceOutput'], '')
displayName: Print signed provenance

Job Summary Report

Cimon Attest uploads the provenance document as a job summary for the Azure Pipelines job, which is available in the "Extensions" tab. The report could be turned off by introducing the reportJobSummary: false parameter. Additional info for how it works can be found here.

Output Artifacts

Cimon Attest uploads the provenance document as an artifact for the Azure Pipelines job so that it will be available for download and optionally transferred to the consumers. The artifact upload could be turned off by introducing the reportArtifact: false parameter. Additional info for publishing and downloading job artifacts can be found here.

Cimon Integration with Cycode

Cimon Attest uploads signed or unsigned provenance documents to the Cycode platform for storage, enrichment, and verification. For that, you need to supply the task with service account credentials or personal access token, together with the endpoint URL:

steps:
- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
url: "$(CIMON_URL)"
subjects: $(hashes)
signKey: $(signKey)

Examples

The following examples use Azure Pipelines task syntax but apply to all other implementations of Cimon Attest for different platforms.

Generate provenance for given subjects without signature

steps:
- script: |
mkdir dist
echo artifact123 > dist/artifact1
echo artifact321 > dist/artifact2
displayName: "Build artifacts"

- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: |
dist/artifact1
dist/artifact2

Generate provenance for given subjects with signature

steps:
- script: |
mkdir dist
echo artifact123 > dist/artifact1
echo artifact321 > dist/artifact2
displayName: "Build artifacts"

- script: |
openssl genrsa -out private-key.pem 3072
displayName: Generate sign key

- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: |
dist/artifact1
dist/artifact2
signKey: private-key.pem

Generate provenance for the entire directory

steps:
- script: |
mkdir dist
echo artifact123 > dist/artifact1
echo artifact321 > dist/artifact2
displayName: "Build artifacts"

- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: |
dist

Generate provenance for predefined subjects with designated hashes

steps:
- script: |
mkdir dist
echo artifact123 > dist/artifact1
echo artifact321 > dist/artifact2

echo "##vso[task.setvariable variable=hashes]$(sha256sum dist/artifact1 dist/artifact2 | base64 -w0)"
displayName: "Build artifacts and calculate hashes"

- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: $(hashes)

Generate provenance for an container image reference

steps:
- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: "cycodelabs/cimon@sha256:ad4ab84178621f359a5ec1ba9eff8ba46626d8d1999416646b6aaa96bfcbf802"

Generate provenance and upload it together with the artifacts

steps:
- script: |
mkdir dist
echo artifact123 > dist/artifact1
echo artifact321 > dist/artifact2
displayName: "Build artifacts"

- task: CimonAttest@0
inputs:
clientId: "$(CIMON_CLIENT_ID)"
secret: "$(CIMON_SECRET)"
subjects: |
dist
reportArtifact: false
provenanceOutput: dist/provenance.jsonl

- publish: dist
artifact: myartifact