Skip to content

testifysec/dagger-witness

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dagger-witness

Supply-chain attestation for Dagger pipelines using the in-toto Witness framework.

Features

  • Zero-config attestation: Automatically generate attestations for every WithExec call
  • Explicit control: Fine-grained control over attestation with WitnessExec and Wrap
  • 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

Quick Start (< 60 seconds to first attestation)

Installation

# 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

Zero-Config Mode (Auto)

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

Explicit Mode

// 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")

API Reference

Core Types

// 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

Key Methods

  • New(client) - Create witness instance
  • WithSignerPEM(secret) - Configure signing key
  • Auto() - Get proxy client for automatic attestation
  • Wrap(container) - Wrap container for explicit control
  • WitnessExec(ctx, ctr, step, args, opts) - Execute with attestation
  • ExportAttestations(dir) - Write DSSE files
  • RequireAll(ctx, policy) - Verify attestations

What's in an Attestation?

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..."
  }]
}

Demo

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.

Roadmap

v0.1 (Current)

  • ✓ Auto() proxy for zero-config
  • ✓ Explicit Wrap() and WitnessExec()
  • ✓ Default attestors (command, env, git)
  • ✓ PEM signing
  • ✓ DSSE export
  • ✓ Minimal policy verification

v0.2 (Next)

  • OTel correlation (link to Dagger traces)
  • Archivista upload
  • KMS signers (AWS, GCP, Azure)
  • OCI attestor
  • Linux tracing (opt-in)

v0.3 (Future)

  • Custom attestor plugins
  • Advanced OPA policies
  • SLSA provenance generation
  • Rekor transparency log

Architecture

┌─────────────┐
│  Dagger     │
│  Pipeline   │
└──────┬──────┘
       │
┌──────▼──────┐
│ witness-lite│
│   Module    │
└──────┬──────┘
       │
┌──────▼──────────────────┐
│   go-witness library    │
│ ┌──────┐ ┌──────┐ ┌───┐│
│ │Attest│ │ Sign │ │OPA││
│ └──────┘ └──────┘ └───┘│
└─────────────────────────┘
       │
┌──────▼──────┐
│    DSSE     │
│Attestations │
└─────────────┘

Why witness-lite?

  1. Immediate value: Get attestations without rewriting pipelines
  2. Zero learning curve: Works with existing Dagger code
  3. Production ready: Based on proven in-toto/witness ecosystem
  4. Growth path: Start simple, add features as needed

Links

License

Apache 2.0

About

Supply-chain attestation for Dagger pipelines

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages