Generate and store SLSA provenance
Supply-chain levels for software artifacts (SLSA and pronounced like "salsa") is an industry-consensus specification for describing and gradually improving artifact supply chain security.
When using Buildkite Pipelines with Package Registries, you can publish software packages and artifacts to registries with SLSA provenance in only four steps.
This guide uses the following Buildkite examples to demonstrate this process:
- Buildkite organization:
nova-corp
- Pipeline:
ruby-logger-gem
, which builds a RubyGem package - Registry:
ruby-gems
to store the RubyGem
Although this guide uses RubyGems as examples, this process will work for all supported package ecosystems (with the exception of OCI-based packages like Container (Docker) and Helm OCI).
Step 1: Configure steps to generate SLSA provenance
The Generate Provenance Attestation Buildkite Plugin generates a SLSA provenance attestation for artifacts that have been uploaded to artifact storage in a pipeline step.
First, configure a step step that builds a RubyGem gem and uploads it to artifact storage.
steps:
- label: "Build Gem"
command: "gem build logger.gemspec"
artifact_paths: "logger-*.gem"
A SLSA provenance attestation can be generated by adding this plugin to your pipeline step that builds the package or artifact:
steps:
- label: "Build Gem"
command: "gem build logger.gemspec"
artifact_paths: "logger-*.gem"
plugins:
- generate-provenance-attestation#v1.1.0:
artifacts: "logger-*.gem"
attestation_name: "gem-attestation.json"
In the example above, a SLSA provenance attestation will be generated for artifacts matching logger-*.gem
and be uploaded it to artifact storage as gem-attestation.json
.
Once this step is complete, gem-attestation.json
will be available to subsequent steps in the pipeline.
See an example of a SLSA provenance statement that this plugin generates. This SLSA provenance statement is then serialized and uploaded as a dead simple signing envelope (DSSE). This envelope.json
DSSE file shows an example of the gem-attestation.json
file format. Learn more about DSSE in DSSE Envelope.
Step 2: Configure steps to publish a package with SLSA provenance
The Publish to Packages plugin allows you to quickly and easily publish a package to Package Registries. When the attestations:
attribute is set, the package will be published from artifact storage with the specified attestations.
steps:
- label: "Publish Gem"
plugins:
- publish-to-packages#v2.2.0:
artifacts: "logger-*.gem"
registry: "nova-corp/ruby-gems"
attestations:
- "gem-attestation.json"
In the example above, artifacts matching logger-*.gem
will be published to nova-corp/ruby-gems
Package Registry. Additionally, they will be published with the gem-attestation.json
attestation.
Step 3: Define an OIDC policy for the registry
The Publish to Packages plugin authenticates with Package Registries using an Agent OIDC token. Therefore, an OIDC policy must be configured on the Ruby registry.
In the example above, the policy allows the Buildkite pipeline with slug ruby-logger-gem
, configured in the Nova Corp Buildkite organization (with slug nova-corp
) to publish packages to the Ruby registry named ruby-gems.
Step 4: Complete the pipeline
All the steps above come together in a simple pipeline that builds and publishes a Ruby Gem with SLSA Provenance. A step dependency ensures that the Publish Gem step does not start until the Build Gem step has finished successfully.
This generates a build that looks something like this:
The SLSA provenance will then be visible under the Attestations tab of a package details page.
Summary
SLSA Provenance can be generated and stored in Buildkite with the help of Generate Provenance Attestation and Publish to Packages plugins.
Artifacts that are built and published in this way satisfy SLSA Build Level 1 requirements.