Securing the Conda Package Supply Chain with Sigstore
)
Sigstore now generally available
We're pleased to announce that sigstore support is now in public beta on prefix.dev! This has been a long time coming and we are excited to announce that we worked together with the community to make it happen under the Conda Enhancement Proposal 27.
What does sigstore support mean?
Sigstore is a way to cryptographically sign packages (or any binary artifacts, really). It was pioneered in the container space, but has been adopted by many packaging ecosystems over the past years: PyPI, Python releases, Rust crates, Homebrew, and Rubygems – just to name a few. At prefix.dev we have worked with Trail Of Bits to ensure that the Conda ecosystem is ready to use Sigstore attestations as a means to cryptographically sign packages as well.
What does a Sigstore attestation mean?
A Sigstore attestation will tie the producer of a package (for example a GitHub Actions workflow) to the package artifact uploaded on prefix.dev – thanks to Trusted Publishing, this is smooth and verifiable.
When the attestation is created, metadata about the artifact is registered in a "Transparency Log" which we can inspect at all times. The metadata contains information such as:
The name of the package
The SHA256 hash of the package data (you can use this to find the log entry!)
The CI workflow that built the package
The repository Git hash that contained the CI workflow
The organization and the username that built the package
Thus, using this information we can attest that a given package was created and uploaded by a certain GitHub organization, and this is transparently logged on our server and the Sigstore public good instance.
Part of the attestation is also a "predicate" that collects facts about the artifact that is signed. We went through a lengthy process together with the Conda community to design this predicate – with the help of Trail of Bits (thank you, William Woodruff and Facundo Tuesca!) – which resulted in CEP-27 which provides all the technical details.
The in-toto attestation with the v1 Conda predicate contains the following facts about the package:
The SHA256 hash of the package (guaranteed to be unique)
The full filename (
{name}-{version}-{buildstring}.conda
)Optionally, the predicate, which contains the full URL to the target channel, for example:
https://prefix.dev/my-channel
(the channel URL is defined as the place where you would attachnoarch/repodata.json
).
How to create your own Sigstore attestations
GitHub Actions make it very easy to create your own Sigstore attestations. Simply run rattler-build (or pixi-build) to build your package, run the attest
action over it, and upload the package together with the attestation using Trusted Publishing to a Conda channel on prefix.dev. We are the first and only Conda channel offering with Trusted Publishing & sigstore support.
name: Package and sign
on: [push]
jobs:
build:
# These permissions are needed to create a sigstore certificate.
permissions:
id-token: write
contents: read
attestations: write
name: Build package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build conda package
uses: prefix-dev/rattler-build-action@v0.2.34
# We are using Github's official attest action to create a sigstore certificate with
# the Conda predicate.
- uses: actions/attest@v1
id: attest
with:
subject-path: "**/*.conda"
predicate-type: "https://schemas.conda.org/attestations-publish-1.schema.json"
predicate: "{\"targetChannel\": \"https://prefix.dev/sigstore-example\"}"
# Note: no API keys needed because we have configured a trusted publisher!
- name: Upload the package
run: |
rattler-build upload prefix -c sigstore-example ./output/**/*.conda --attestation ${{ steps.attest.outputs.bundle-path }}
You will then be able to find the attestations on:
Github: https://github.com/prefix-dev/sigstore-example/attestations/10209596
The public goods instance of sigstore: https://search.sigstore.dev/?logIndex=456061810
Prefix.dev: https://prefix.dev/channels/sigstore-example/packages/signed-package
We have a comprehensive example that also shows how to verify the signatures using the gh
CLI. It's possible to validate signatures using cosign
, sigstore-python
or sigstore-ruby
as well, of course. The full source code for the example and an extensive README can be found here: https://github.com/prefix-dev/sigstore-example.
What's next
As we're rolling out the Sigstore support on prefix.dev as a public beta, we hope to see many of our users try it out. During the beta phase, it will be free for everyone. It will always remain free for public open source channels. For users with private channels or public channels distributing closed source software, we will roll out pricing tiers later this year.
If you are interested in using Sigstore, but your organizations needs are not met with our current GitHub Actions integration, we would love to chat. It is absolutely possible to support Gitlab or other CI providers that implement OIDC for trusted publishing and Sigstore attestations and we are happy to prioritize this based on demand.
We are happy to take the next step in modernizing the Conda ecosystem and to provide the fastest and most modern conda channel experience in the world (with sharded repodata, trusted publishing, Sigstore, and more ground breaking features coming soon)!
The Sigstore CEP-27 was made possible thanks to a Small Development Grant by NumFOCUS. And again, a big thank you to our collaborators from Trail of Bits for helping us to push this over the finish line and their tremendous insights into Software Supply Chain Security with Sigstore.
There are a number of next steps for software supply chain security for the Conda ecosystem that we are envisioning:
Re-evaluate TUF (The Update Framework) to secure
repodata.json
Think about "counter-signing" for an even stronger link between target channel and the artifact (this would add a transparency log entry when the server receives the package). NPM does this for their sigstore implementation.
Add a protocol to make it easier to retrieve the attestations (e.g. make the attestations available as a bundle under
package-name.conda.sigstore
right next to the package file)
We are lucky to have been awarded an OpenSSF grant to continue this work! If you are interested in discussing these items, join the Conda Community calls where we present our ideas regularly or join our Discord server to chat!
