Supply-chain attestation for Dagger pipelines using the in-toto Witness framework.
- Zero-config attestation: Automatically generate attestations for every
WithExec
call - Explicit control: Fine-grained control over attestation with
WitnessExec
andWrap
- Default attestors: command-run, env, git (with optional materials/products)
- PEM signing: Simple secret-based signing (KMS support coming in v0.2)
- DSSE output: Standard in-toto attestation format
- Policy verification: Built-in minimal policy for basic verification
# Use directly from Daggerverse
dagger call -m github.com/testifysec/dagger-witness@main \
new \
with-signer-pem --pem-key=file:./my-key.pem \
witness-exec --container=... --step="build" --args="go","build"
# Or add as dependency to your module
dagger install github.com/testifysec/dagger-witness@main
package main
import (
"context"
"dagger.io/dagger"
)
func main() {
ctx := context.Background()
c, _ := dagger.Connect(ctx)
defer c.Close()
// Setup witness with PEM key
w := c.WitnessLite().
New(c).
WithSignerPEM(c.SetSecret("w_key", pemData)).
Auto()
defer w.ExportAttestations("dist/attestations")
// Your normal pipeline - automatically attested!
src := c.Host().Directory("./app")
ctr := w.Container().From("golang:1.22").
WithDirectory("/src", src).
WithWorkdir("/src").
WithExec([]string{"go", "build", "-o", "hello", "."}) // ✓ Attested
w.Container().From("anchore/syft:latest").
WithDirectory("/src", src).
WithWorkdir("/src").
WithExec([]string{"syft", ".", "-o", "spdx-json"}) // ✓ Attested
}
Result: dist/attestations/
contains 01-go-build.dsse.json
and 02-syft.dsse.json
// For fine-grained control
wrap := witness.Wrap(ctr)
ctr, buildAttest := wrap.Exec("build", []string{"go", "build"}, nil)
// With materials and products tracking
ctr, sbomAttest := witness.WitnessExec(
ctx, ctr, "sbom",
[]string{"syft", ".", "-o", "spdx-json"},
&ExecOpts{Materials: true, Products: true},
)
// Export individual attestations
buildAttest.Export(ctx, "dist/attestations/build.dsse.json")
sbomAttest.Export(ctx, "dist/attestations/sbom.dsse.json")
// Main module
type WitnessLite struct{}
// Execution options
type ExecOpts struct {
Materials bool // Track input artifacts
Products bool // Track output artifacts
}
// Policy presets
type PolicyPreset string
const PolicyMinimal PolicyPreset = "minimal" // signed + exit=0 + git
New(client)
- Create witness instanceWithSignerPEM(secret)
- Configure signing keyAuto()
- Get proxy client for automatic attestationWrap(container)
- Wrap container for explicit controlWitnessExec(ctx, ctr, step, args, opts)
- Execute with attestationExportAttestations(dir)
- Write DSSE filesRequireAll(ctx, policy)
- Verify attestations
Each DSSE file contains:
- Command: argv, exit code, environment
- Git: commit hash, branch, remote URL
- Materials/Products: file hashes (when enabled)
- Signature: PEM key signature with key ID
Example structure:
{
"payload": "eyJ0eXBlIjoiaW4tdG90by9TdGF0ZW1lbnQifQ...",
"payloadType": "application/vnd.in-toto+json",
"signatures": [{
"sig": "MEUCIQDx...",
"keyid": "SHA256:abc123..."
}]
}
Run the included demo to see attestations in action:
cd examples/demo
dagger run go run .
ls -la dist/attestations/
The demo shows both auto and explicit modes with a simple Go app build + SBOM generation.
- ✓ Auto() proxy for zero-config
- ✓ Explicit Wrap() and WitnessExec()
- ✓ Default attestors (command, env, git)
- ✓ PEM signing
- ✓ DSSE export
- ✓ Minimal policy verification
- OTel correlation (link to Dagger traces)
- Archivista upload
- KMS signers (AWS, GCP, Azure)
- OCI attestor
- Linux tracing (opt-in)
- Custom attestor plugins
- Advanced OPA policies
- SLSA provenance generation
- Rekor transparency log
┌─────────────┐
│ Dagger │
│ Pipeline │
└──────┬──────┘
│
┌──────▼──────┐
│ witness-lite│
│ Module │
└──────┬──────┘
│
┌──────▼──────────────────┐
│ go-witness library │
│ ┌──────┐ ┌──────┐ ┌───┐│
│ │Attest│ │ Sign │ │OPA││
│ └──────┘ └──────┘ └───┘│
└─────────────────────────┘
│
┌──────▼──────┐
│ DSSE │
│Attestations │
└─────────────┘
- Immediate value: Get attestations without rewriting pipelines
- Zero learning curve: Works with existing Dagger code
- Production ready: Based on proven in-toto/witness ecosystem
- Growth path: Start simple, add features as needed
Apache 2.0