Sign Artifacts in CI/CD
This guide shows how to sign artifacts in CI/CD pipelines using ambient OIDC credentials.
GitHub Actions
In GitHub Actions, the workflow automatically has an OIDC identity token available. Sigstore uses this to issue a short-lived signing certificate — no long-lived secrets needed.
Workflow Setup
# .github/workflows/release.yml
name: Release
on:
push:
tags: ['v*']
permissions:
id-token: write # Required for Sigstore OIDC
contents: read
jobs:
build-and-sign:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0'
- name: Build
run: dotnet build -c Release
- name: Sign artifact
run: dotnet run --project tools/sign -- artifacts/myapp.tar.gz
Signing Code
using Sigstore;
// In CI, SigstoreSigner automatically detects ambient OIDC credentials
var signer = new SigstoreSigner(fulcioClient, rekorClient, tsaClient, oidcProvider);
await using var artifact = File.OpenRead(args[0]);
var bundle = await signer.SignAsync(artifact);
await bundle.SaveAsync(new FileInfo($"{args[0]}.sigstore.json"));
Console.WriteLine($"Signed! Rekor log index: {bundle.VerificationMaterial?.TlogEntries[0].LogIndex}");
Verifying the Signed Artifact
Consumers verify by pinning to your repository:
var verifier = new SigstoreVerifier();
var policy = new VerificationPolicy
{
CertificateIdentity = CertificateIdentity.ForGitHubActions(
owner: "myorg",
repository: "myapp",
workflowRef: "refs/tags/v1.0.0")
};
var result = await verifier.VerifyFileAsync(
new FileInfo("myapp.tar.gz"),
new FileInfo("myapp.tar.gz.sigstore.json"),
policy);
Signing DSSE Attestations (In-Toto)
For supply chain attestations (SLSA provenance, SBOMs):
var statement = """
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [{"name": "myapp.tar.gz", "digest": {"sha256": "abc123..."}}],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": { ... }
}
""";
var bundle = await signer.AttestAsync(statement);
await bundle.SaveAsync(new FileInfo("myapp.tar.gz.intoto.sigstore.json"));
What Happens During Signing
- OIDC Authentication — obtains an identity token from the CI provider
- Ephemeral Key — generates a one-time ECDSA P-256 keypair
- Certificate — Fulcio issues a short-lived certificate binding the OIDC identity
- Sign — signs the artifact hash with the ephemeral private key
- Timestamp — gets an RFC 3161 signed timestamp
- Transparency Log — records the signing event in Rekor
- Bundle — packages everything into a
.sigstore.jsonfile - Key Destruction — the ephemeral private key is destroyed
See Also
- Sign Interactively — signing from a developer workstation
- Verify GitHub Actions Artifacts — verifying signed CI artifacts