6.5 KiB
Delta Attestation Workflow Guide
Audience: CI/CD engineers, release operators, security auditors
Purpose: End-to-end guide for generating, signing, attaching, verifying, and exporting delta-sig attestations.
Sprint: SPRINT_20260122_040_Platform_oci_delta_attestation_pipeline
Overview
The delta attestation workflow provides verifiable evidence of binary-level changes between releases. It covers the full lifecycle from generating a delta-sig predicate through to offline bundle verification.
diff → attest → attach → verify → export → offline-verify
Prerequisites
stellaCLI installed and configured- EC signing key (PEM format) for attestation signing
- Access to target OCI registry (for attach/verify)
- (Optional) Rekor transparency log URL for public verifiability
Step 1: Generate Delta-Sig Predicate
Compare two binary builds to produce a delta-sig predicate describing function-level changes:
stella binary delta-sig diff \
--old /path/to/old-binary \
--new /path/to/new-binary \
--output delta-predicate.json \
--arch linux-amd64
The predicate JSON follows the https://stellaops.dev/delta-sig/v1 schema and includes:
subject[]- Old and new binary references with digestsdelta[]- Function-level changes (added, removed, modified)summary- Aggregate change statisticstooling- Lifter and diff algorithm metadatalargeBlobs[]- References to binary patches or SBOM fragments (optional)sbomDigest- Digest of the associated canonical SBOM (optional)
Step 2: Sign and Attest
Sign the predicate with an EC key, producing a DSSE envelope. Optionally submit to a Rekor transparency log:
stella binary delta-sig attest \
--predicate delta-predicate.json \
--key signing-key.pem \
--output signed-envelope.dsse.json \
--rekor-url https://rekor.sigstore.dev \
--receipt rekor-receipt.json \
--verbose
Output:
signed-envelope.dsse.json- DSSE envelope with in-toto v1 statementrekor-receipt.json- Rekor inclusion proof (UUID, log index, integrated time)
Without Rekor (air-gapped environments):
stella binary delta-sig attest \
--predicate delta-predicate.json \
--key signing-key.pem \
--output signed-envelope.dsse.json
Step 3: Attach to OCI Image
Attach the signed attestation to the target OCI image via ORAS referrers:
stella attest attach \
--image registry.example.com/app:v1.2 \
--attestation signed-envelope.dsse.json \
--verbose
The attestation is stored as a referrer artifact in the registry, discoverable by image digest.
Step 4: Verify Attestations
Verify that attestations are properly attached and valid:
stella attest verify \
--image registry.example.com/app:v1.2 \
--predicate-type "https://stellaops.dev/delta-sig/v1" \
--require-rekor \
--verbose
This checks:
- DSSE envelope signature validity
- Predicate type matches expected schema
- Rekor annotations are present and valid (when
--require-rekor)
Step 5: Export Evidence Bundle
Export all attestation evidence for offline environments:
# Light mode (metadata only, small size)
stella evidence export-bundle \
--image registry.example.com/app:v1.2 \
--output evidence-light.tar.gz
# Full mode (includes binary blobs for replay)
stella evidence export-bundle \
--image registry.example.com/app:v1.2 \
--output evidence-full.tar.gz \
--full
Bundle Contents
Light bundle:
bundle/
├── manifest.json # exportMode: "light"
└── attestations/
└── delta-sig.dsse.json
Full bundle:
bundle/
├── manifest.json # exportMode: "full"
├── attestations/
│ └── delta-sig.dsse.json
└── blobs/
├── sha256-<hex1> # Binary patch
└── sha256-<hex2> # SBOM fragment
Step 6: Offline Bundle Verification
Verify the exported bundle in air-gapped environments:
# Full bundle: self-contained verification with blob replay
stella bundle verify \
--bundle evidence-full.tar.gz \
--offline \
--trust-root /etc/stellaops/tsa-root.pem \
--replay \
--verbose
# Light bundle: provide local blob source for replay
stella bundle verify \
--bundle evidence-light.tar.gz \
--offline \
--replay \
--blob-source /path/to/cached-blobs/
Verification Steps
| Step | Check | Failure Behavior |
|---|---|---|
| 1 | Manifest checksum | Fatal |
| 2 | Blob digests | Fatal |
| 3 | DSSE signatures | Fatal |
| 4 | Rekor proofs | Fatal (if checkpoint provided) |
| 5 | RFC 3161 timestamps | Fatal (in strict mode) |
| 6 | Payload type expectations | Warning (fatal in strict) |
| 7 | Blob replay | Fatal (when --replay enabled) |
CI/CD Integration Example
# .gitea/workflows/release.yaml
jobs:
attest:
steps:
- name: Generate delta predicate
run: |
stella binary delta-sig diff \
--old ${{ steps.build.outputs.old_binary }} \
--new ${{ steps.build.outputs.new_binary }} \
--output delta-predicate.json
- name: Sign and submit to Rekor
run: |
stella binary delta-sig attest \
--predicate delta-predicate.json \
--key ${{ secrets.SIGNING_KEY_PATH }} \
--output envelope.dsse.json \
--rekor-url https://rekor.sigstore.dev \
--receipt rekor-receipt.json
- name: Attach to image
run: |
stella attest attach \
--image ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ env.TAG }} \
--attestation envelope.dsse.json
- name: Export full bundle for auditors
run: |
stella evidence export-bundle \
--image ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ env.TAG }} \
--output evidence-bundle.tar.gz \
--full
Troubleshooting
| Issue | Cause | Resolution |
|---|---|---|
Blob Replay ✗ |
Missing blobs in light bundle | Use --blob-source or export with --full |
DSSE signature ✗ |
Key mismatch | Verify signing key matches trusted keys |
Rekor proof ✗ |
No checkpoint provided | Add --rekor-checkpoint for offline |
| Exit code 2 | Invalid predicate JSON | Check required fields: subject, delta, summary, tooling, computedAt |