- Implement `SbomIngestServiceCollectionExtensionsTests` to verify the SBOM ingestion pipeline exports snapshots correctly. - Create `SbomIngestTransformerTests` to ensure the transformation produces expected nodes and edges, including deduplication of license nodes and normalization of timestamps. - Add `SbomSnapshotExporterTests` to test the export functionality for manifest, adjacency, nodes, and edges. - Introduce `VexOverlayTransformerTests` to validate the transformation of VEX nodes and edges. - Set up project file for the test project with necessary dependencies and configurations. - Include JSON fixture files for testing purposes.
5.1 KiB
Portable Evidence Bundles (Sealed/Air-Gapped)
Sprint 160 · Task EVID-OBS-60-001
Audience: Evidence Locker operators, Air-Gap controllers, incident responders
Portable bundles let operators hand off sealed evidence across enclaves without exposing tenant identifiers or internal storage coordinates. The Evidence Locker produces a deterministic archive (portable-bundle-v1.tgz) that carries the manifest + signature alongside redacted metadata, checksum manifest, and an offline verification script.
1. When to use the portable flow
- Sealed mode exports. Regulatory or incident response teams that cannot access the primary enclave directly.
- Chain-of-custody transfers. Moving evidence into offline review systems while keeping the DSSE provenance intact.
- Break-glass rehearsals. Validating incident response playbooks without exposing internal bundle metadata.
Avoid portable bundles for regular intra-enclave automation; the full bundle.tgz already carries richer metadata for automated tooling.
2. Generating the bundle
-
Seal the evidence bundle as usual (
POST /evidence/snapshotor via CLI). -
Request the portable artefact using the new endpoint:
GET /evidence/{bundleId}/portable Scope: evidence:readResponse headers mirror the standard download (
application/gzip,Content-Disposition: attachment; filename="portable-evidence-bundle-{bundleId}.tgz").
The Evidence Locker caches the portable archive using write-once semantics. Subsequent requests reuse the existing object and the audit log records whether the file was newly created or served from cache.
3. Archive layout
portable-bundle-v1.tgz
├── manifest.json # Canonical bundle manifest (identical to sealed bundle)
├── signature.json # DSSE signature + optional RFC3161 timestamp (base64 token)
├── bundle.json # Redacted metadata (bundleId, kind, rootHash, timestamps, incidentMetadata)
├── checksums.txt # Merkle root + per-entry SHA-256 digests
├── instructions-portable.txt # Human-readable guidance for sealed transfers
└── verify-offline.sh # POSIX shell helper (extract + checksum verify + reminder to run DSSE verification)
Redaction rules:
- No tenant identifiers, storage keys, descriptions, or free-form metadata.
- Incident metadata is retained only under the
incidentMetadataobject (incident.mode,incident.changedAt, etc.). portableGeneratedAtrecords when the archive was produced so downstream systems can reason about freshness.
4. Offline verification workflow
-
Copy
portable-bundle-v1.tgzinto the sealed environment (USB, sneaker-net, etc.). -
Run the included helper from a POSIX shell:
chmod +x verify-offline.sh ./verify-offline.sh portable-bundle-v1.tgzThe script:
- extracts the archive into a temporary directory,
- validates
checksums.txtusingsha256sum(orshasum -a 256), and - prints the Merkle root hash from
bundle.json.
-
Complete provenance verification:
- Preferred:
stella evidence verify --bundle portable-bundle-v1.tgz - Alternative: supply
manifest.jsonandsignature.jsonto the evidence verifier library.
- Preferred:
-
Record the verification output (root hash, timestamp) with the receiving enclave’s evidence locker or incident ticket.
Note: The DSSE payload is unchanged from the sealed bundle, so existing verification tooling does not need special handling for portable archives.
5. Importing into the receiving enclave
- Upload the archive to the target Evidence Locker or attach it to the incident record.
- Store the checksum report generated by
verify-offline.shalongside the archive. - If downstream automation needs enriched metadata, attach a private note referencing the original bundle’s tenant context—the portable archive intentionally omits it.
6. Troubleshooting
| Symptom | Likely cause | Remediation |
|---|---|---|
verify-offline.sh reports checksum failures |
Transfer corruption | Re-transfer artefact; run sha256sum portable-bundle-v1.tgz on both sides and compare. |
stella evidence verify cannot reach TSA |
Sealed environment lacks TSA connectivity | Verification still succeeds using DSSE signature; capture the missing TSA warning in the import log. |
/portable endpoint returns 400 |
Bundle not yet sealed or signature missing | Wait for sealing to complete; ensure DSSE signing is enabled. |
/portable returns 404 |
Bundle not found or tenant mismatch | Confirm DPoP scope and tenant claim; refresh bundle status via GET /evidence/{id}. |
7. Change management
- Portable bundle versioning is encoded in the filename (
portable-bundle-v1.tgz). When content or script behaviour changes, bump the version and announce in release notes. - Any updates to
verify-offline.shmust remain POSIX-sh compatible and avoid external dependencies beyondtar,sha256sum/shasum, and standard coreutils. - Remember to update this guide and the bundle packaging dossier (
docs/modules/evidence-locker/bundle-packaging.md) when fields or workflows change.