Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- 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.
91 lines
5.1 KiB
Markdown
91 lines
5.1 KiB
Markdown
# 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
|
||
|
||
1. Seal the evidence bundle as usual (`POST /evidence/snapshot` or via CLI).
|
||
2. Request the portable artefact using the new endpoint:
|
||
|
||
```
|
||
GET /evidence/{bundleId}/portable
|
||
Scope: evidence:read
|
||
```
|
||
|
||
Response 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 `incidentMetadata` object (`incident.mode`, `incident.changedAt`, etc.).
|
||
- `portableGeneratedAt` records when the archive was produced so downstream systems can reason about freshness.
|
||
|
||
## 4. Offline verification workflow
|
||
|
||
1. Copy `portable-bundle-v1.tgz` into the sealed environment (USB, sneaker-net, etc.).
|
||
2. Run the included helper from a POSIX shell:
|
||
|
||
```sh
|
||
chmod +x verify-offline.sh
|
||
./verify-offline.sh portable-bundle-v1.tgz
|
||
```
|
||
|
||
The script:
|
||
- extracts the archive into a temporary directory,
|
||
- validates `checksums.txt` using `sha256sum` (or `shasum -a 256`), and
|
||
- prints the Merkle root hash from `bundle.json`.
|
||
|
||
3. Complete provenance verification:
|
||
- Preferred: `stella evidence verify --bundle portable-bundle-v1.tgz`
|
||
- Alternative: supply `manifest.json` and `signature.json` to the evidence verifier library.
|
||
|
||
4. 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
|
||
|
||
1. Upload the archive to the target Evidence Locker or attach it to the incident record.
|
||
2. Store the checksum report generated by `verify-offline.sh` alongside the archive.
|
||
3. 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.sh` must remain POSIX-sh compatible and avoid external dependencies beyond `tar`, `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.
|