Workflow Contract
A Workflow Contract defines the expectations of what content a workflow must send as part of their attestation. For example, a contract could explicitly state that the URI@digest of the generated container image, the container rootfs used during build, and the Software Bill of Materials of that container image must be present in the attestation.
There are two additional properties of Workflow Contracts that aims to ease the management of workflows in your organization
- A Workflow Contract is immutable and versioned, new revisions of the contract with new/different requirements can be added over time. This is especially useful for iterative integrations.
- A Workflow Contract can belong to more than one Workflow. This means that a change in a single contract will be propagated to many workflows. This is especially useful for org-wide standardization and fleet management.
Example: three CI/CD pipelines associated with their respective Chainloop workflows. Two of those Workflows are sharing the same Contract (using the same or different revision).
A Workflow Contract can be provided in json
, yaml
or cue
formats.
A full example of a Workflow Contract looks like
- yaml
- cue
- json
schemaVersion: v1
# Arbitrary set of annotations can be added to the contract and will be part of the attestation
annotations:
- name: version
value: oss # if the value is left empty, it will be required and resolved at attestation time
# https://docs.chainloop.dev/reference/operator/material-types
materials:
# CONTAINER_IMAGE kinds will get resolved to retrieve their repository digest
- type: CONTAINER_IMAGE
name:
skynet-control-plane
# The output flag indicates that the material will be part of the attestation subject
output: true
# Arbitrary annotations can be added to the material
annotations:
- name: component
value: control-plane
# The value can be left empty so it can be provided at attestation time
- name: asset
# ARTIFACT kinds will first get uploaded to your artifact registry via the built-in Content Addressable Storage (CAS)
# Optional dockerfile
- type: ARTIFACT
name: dockerfile
optional: true
# SBOMs will be uploaded to the artifact registry and referenced in the attestation
# Both SBOM_CYCLONEDX_JSON and SBOM_SPDX_JSON are supported
- type: SBOM_CYCLONEDX_JSON
name: skynet-sbom
# CSAF_VEX and OPENVEX are supported
- type: OPENVEX
name: disclosure
# And static analysis reports in SARIF format
- type: SARIF
name: static-out
# or additional tools
- type: TWISTCLI_SCAN_JSON
name: scan-result
# https://docs.chainloop.dev/reference/policies
policies:
materials: # policies applied to materials
- ref: file://cyclonedx-licenses.yaml
attestation: # policies applied to the whole attestation
- ref: https://github.com/chainloop/chainloop-dev/blob/main/docs/examples/policies/chainloop-commit.yaml # (2)
# Env vars we want the system to resolve and inject during attestation initialization
# Additional ones can be inherited from the specified runner context below
envAllowList:
- CUSTOM_VAR
# Enforce in what runner context the attestation must happen
# If not specified, the attestation crafting process is allowed to run anywhere
runner:
type: "GITHUB_ACTION"
schemaVersion: "v1"
// Arbitrary set of annotations can be added to the contract and will be part of the attestation
annotations: [
{
name: "version"
value: "oss" // if the value is left empty, it will be required and resolved at attestation time
}
]
// Three required and one optional materials of three different kinds
// The output flag indicates that the material will be part of the attestation subject
materials: [
// CONTAINER_IMAGE kinds will get resolved to retrieve their repository digest
{
type: "CONTAINER_IMAGE"
name: "skynet-control-plane"
output: true
// Arbitrary annotations can be added to the material
annotations: [
{
name: "component"
value: "control-plane"
},
{
// The value can be left empty so it can be provided at attestation time
name: "asset"
},
]
},
// ARTIFACT kinds will first get uploaded to the built-in Content Addressable Storage (CAS)
{type: "ARTIFACT", name: "rootfs"},
{type: "ARTIFACT", name: "dockerfile", optional: true},
// STRING kind materials will be injected as simple keypairs
{type: "STRING", name: "build-ref"},
// SBOMs will be uploaded to the CAS and referenced in the attestation
// Both SBOM_CYCLONEDX_JSON and SBOM_SPDX_JSON are supported
{type: "SBOM_CYCLONEDX_JSON", name: "skynet-sbom"},
// CSAF_VEX and OPENVEX are supported
{type: "OPENVEX", name: "disclosure"},
// And static analysis reports in SARIF format
{type: "SARIF", name: "static-out"},
]
// Env vars we want the system to resolve and inject during attestation initialization
// Additional ones can be inherited from the specified runner context below
envAllowList: [ "CUSTOM_VAR"]
// Enforce in what runner context the attestation must happen
// If not specified, the attestation crafting process is allowed to run anywhere
runner: type: "GITHUB_ACTION"
{
"schemaVersion": "v1",
"annotations": [
{
"name": "version",
"value": "oss"
}
],
"materials": [
{
"type": "CONTAINER_IMAGE",
"name": "skynet-control-plane",
"output": true,
"annotations": [
{
"name": "component",
"value": "control-plane"
},
{
"name": "asset"
}
]
},
{ "type": "ARTIFACT", "name": "rootfs" },
{ "type": "ARTIFACT", "name": "dockerfile", "optional": true },
{ "type": "STRING", "name": "build-ref" },
{ "type": "SBOM_CYCLONEDX_JSON", "name": "skynet-sbom" },
{ "type": "OPENVEX", "name": "disclosure" },
{ "type": "SARIF", "name": "static-output" }
],
"envAllowList": ["CUSTOM_VAR"],
"runner": { "type": "GITHUB_ACTION" }
}
Contract Schema
Name | Required | Description |
---|---|---|
schemaVersion | yes | Version of the schema, it needs to be v1 |
materials | no | List of materials to be added to the attestation |
envAllowList | no | List of environment variables that will be resolved and injected in the attestation |
runner | no | Specific runner type associated with this contract. If not set, this contract will be valid to be run anywhere but you'll miss out some of its benefits |
annotations | no | Name/Value pairs of arbitrary annotations that will be added to the attestation. If the value is not provided, it will be required during the attestation process. |
policies | no | Attachments to existing Chainloop policies. See policies reference guide for more information |
Material Schema
The contract can require one or more pieces of evidence (a.k.a material) to be attached during the attestation process.
Name | Required | Default | Description |
---|---|---|---|
name | yes | unique identifier of the material | |
type | yes | Refer to material-types for the list of supported material types. | |
output | no | false | If set to true the material will get injected in the subject section of the in-toto statement. |
optional | no | false | if set to true , providing this material during attestation will be optional. This is useful for soft rollouts of new requirements |
annotations | no | Name/Value pairs of arbitrary annotations that will be added to the attestation. If the value is not provided, it will be required during the attestation process. |
Policy attachments
When defining a contract, a new policies
section can be specified. Policies can be applied to any material, but also to the attestation statement as a whole.
schemaVersion: v1
materials:
- name: sbom
type: SBOM_CYCLONEDX_JSON
- name: another-sbom
type: SBOM_CYCLONEDX_JSON
- name: my-image
type: CONTAINER_IMAGE
policies:
materials: # policies applied to materials
- ref: file://cyclonedx-licenses.yaml # (1)
attestation: # policies applied to the whole attestation
- ref: https://github.com/chainloop/chainloop-dev/blob/main/docs/examples/policies/chainloop-commit.yaml # (2)
Read the docs for full details on policies.
Runner Context
New runner contexts will be added over time. If yours is not implemented yet, please contact us
An optional runner type can be provided in a workflow contract.
schemaVersion: v1
materials:
- type: CONTAINER_IMAGE
name: skynet-control-plane
envAllowList:
- CUSTOM_VAR
runner:
type: "GITHUB_ACTION"
It has the following effect on the attestation process.
- Require the attestation process to be executed in the target runner type unless the
--dry-run
flag is set during initialization. - A link to the workload (i.e Github Action Run link) will be recorded both in the attestation and in the control plane during initialization.
- An additional set of environment variables will be resolved in addition to the ones defined in the contract
envAllowList
.
Currently, we support the following runner types
AZURE_PIPELINE
The following environment variables will be automatically added to the attestation. For more information on what they mean, refer to this link.
BUILD_REQUESTEDFOREMAIL
BUILD_REQUESTEDFOR
BUILD_REPOSITORY_URI
BUILD_REPOSITORY_NAME
BUILD_BUILDID
BUILD_BUILDNUMBER
BUILD_BUILDURI
BUILD_REASON
AGENT_VERSION
TF_BUILD
A link to the Azure Pipeline build will be recorded in the control plane too during initialization.
CIRCLECI_BUILD
The following environment variables will be automatically added to the attestation. For more information on their meaning, refer to the official CircleCI documentation.
CIRCLE_BUILD_URL
CIRCLE_JOB
CIRCLE_BRANCH
(optional)CIRCLE_NODE_TOTAL
CIRCLE_NODE_INDEX
A link to the CircleCI build will be recorded in the control plane too, during initialization.
DAGGER_PIPELINE
To use Chainloop With Dagger you can use this Dagger module
GITHUB_ACTION
The following environment variables will be automatically added to the attestation. For more information on what they do refer to this link.
GITHUB_ACTOR
GITHUB_REF
GITHUB_REPOSITORY
GITHUB_REPOSITORY_OWNER
GITHUB_RUN_ID
GITHUB_SHA
RUNNER_NAME
RUNNER_OS
A link to the Github Action will be recorded in the control plane too during initialization.
GITLAB_PIPELINE
The following environment variables will be automatically added to the attestation. More information about what they mean in Gitlab's official documentation
GITLAB_USER_EMAIL
GITLAB_USER_LOGIN
CI_PROJECT_URL
CI_COMMIT_SHA
CI_JOB_URL
CI_PIPELINE_URL
CI_RUNNER_VERSION
CI_RUNNER_DESCRIPTION
CI_COMMIT_REF_NAME
A link to the Gitlab CI job will be recorded in the control plane too, during initialization.
JENKINS_JOB
The following environment variables will be automatically added to the attestation. For more information on how to use Jenkins environment variables, refer to the official Jenkins documentation.
JOB_NAME
BUILD_URL
GIT_BRANCH
(optional)GIT_COMMIT
(optional)AGENT_WORKDIR
NODE_NAME
A link to the build will be recorded in the control plane too, during initialization.
Remember, if all the env variables that you need are not defined in the context, you can extend such list via the envAllowList
option.