docs consolidation
This commit is contained in:
329
docs/modules/cli/guides/commands/evidence-bundle-format.md
Normal file
329
docs/modules/cli/guides/commands/evidence-bundle-format.md
Normal file
@@ -0,0 +1,329 @@
|
||||
# Evidence Bundle Format Specification
|
||||
|
||||
Version: 1.0
|
||||
Status: Stable
|
||||
Sprint: SPRINT_9200_0001_0003
|
||||
|
||||
## Overview
|
||||
|
||||
Evidence bundles are downloadable archives containing complete evidence packages for findings or scan runs. They enable:
|
||||
|
||||
- **Offline verification**: All evidence is self-contained
|
||||
- **Deterministic replay**: Includes scripts and hashes for verdict reproduction
|
||||
- **Audit compliance**: Provides cryptographic verification of all evidence
|
||||
- **Human readability**: Includes README and manifest for easy inspection
|
||||
|
||||
## Archive Formats
|
||||
|
||||
Evidence bundles are available in two formats:
|
||||
|
||||
| Format | Extension | MIME Type | Use Case |
|
||||
|--------|-----------|-----------|----------|
|
||||
| ZIP | `.zip` | `application/zip` | General use, Windows compatible |
|
||||
| TAR.GZ | `.tar.gz` | `application/gzip` | Unix systems, better compression |
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Single Finding Bundle
|
||||
|
||||
```
|
||||
GET /v1/triage/findings/{findingId}/evidence/export?format=zip
|
||||
```
|
||||
|
||||
Response headers:
|
||||
- `Content-Type: application/zip`
|
||||
- `Content-Disposition: attachment; filename="evidence-{findingId}.zip"`
|
||||
- `X-Archive-Digest: sha256:{digest}`
|
||||
|
||||
### Scan Run Bundle
|
||||
|
||||
```
|
||||
GET /v1/triage/scans/{scanId}/evidence/export?format=zip
|
||||
```
|
||||
|
||||
Response headers:
|
||||
- `Content-Type: application/zip`
|
||||
- `Content-Disposition: attachment; filename="evidence-run-{scanId}.zip"`
|
||||
- `X-Archive-Digest: sha256:{digest}`
|
||||
|
||||
## Finding Bundle Structure
|
||||
|
||||
```
|
||||
evidence-{findingId}/
|
||||
├── manifest.json # Archive manifest with file hashes
|
||||
├── README.md # Human-readable documentation
|
||||
├── sbom.cdx.json # CycloneDX SBOM slice
|
||||
├── reachability.json # Reachability analysis data
|
||||
├── vex/
|
||||
│ ├── vendor.json # Vendor VEX statements
|
||||
│ ├── nvd.json # NVD VEX data
|
||||
│ └── cisa-kev.json # CISA KEV data
|
||||
├── attestations/
|
||||
│ ├── sbom.dsse.json # SBOM DSSE envelope
|
||||
│ └── scan.dsse.json # Scan DSSE envelope
|
||||
├── policy/
|
||||
│ └── evaluation.json # Policy evaluation result
|
||||
├── delta.json # Delta comparison (if available)
|
||||
├── replay-command.txt # Copy-ready replay command
|
||||
├── replay.sh # Bash replay script
|
||||
└── replay.ps1 # PowerShell replay script
|
||||
```
|
||||
|
||||
## Scan Run Bundle Structure
|
||||
|
||||
```
|
||||
evidence-run-{scanId}/
|
||||
├── MANIFEST.json # Run-level manifest
|
||||
├── README.md # Run-level documentation
|
||||
└── findings/
|
||||
├── {findingId1}/
|
||||
│ ├── manifest.json
|
||||
│ ├── README.md
|
||||
│ ├── sbom.cdx.json
|
||||
│ ├── reachability.json
|
||||
│ ├── vex/
|
||||
│ ├── attestations/
|
||||
│ ├── policy/
|
||||
│ ├── delta.json
|
||||
│ ├── replay-command.txt
|
||||
│ ├── replay.sh
|
||||
│ └── replay.ps1
|
||||
├── {findingId2}/
|
||||
│ └── ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Manifest Schema
|
||||
|
||||
### Finding Manifest (manifest.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"findingId": "f-abc123",
|
||||
"generatedAt": "2025-01-15T10:30:00Z",
|
||||
"cacheKey": "sha256:abc123...",
|
||||
"scannerVersion": "10.1.3",
|
||||
"files": [
|
||||
{
|
||||
"path": "sbom.cdx.json",
|
||||
"sha256": "abc123def456...",
|
||||
"size": 12345,
|
||||
"contentType": "application/json"
|
||||
},
|
||||
{
|
||||
"path": "reachability.json",
|
||||
"sha256": "789xyz...",
|
||||
"size": 5678,
|
||||
"contentType": "application/json"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Run Manifest (MANIFEST.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1.0",
|
||||
"scanId": "scan-xyz789",
|
||||
"generatedAt": "2025-01-15T10:30:00Z",
|
||||
"totalFiles": 42,
|
||||
"scannerVersion": "10.1.3",
|
||||
"findings": [
|
||||
{
|
||||
"findingId": "f-abc123",
|
||||
"generatedAt": "2025-01-15T10:30:00Z",
|
||||
"cacheKey": "sha256:abc123...",
|
||||
"files": [...]
|
||||
},
|
||||
{
|
||||
"findingId": "f-def456",
|
||||
"generatedAt": "2025-01-15T10:30:00Z",
|
||||
"cacheKey": "sha256:def456...",
|
||||
"files": [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Replay Scripts
|
||||
|
||||
### Bash Script (replay.sh)
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# StellaOps Evidence Bundle Replay Script
|
||||
# Generated: 2025-01-15T10:30:00Z
|
||||
# Finding: f-abc123
|
||||
# CVE: CVE-2024-1234
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Input hashes for deterministic replay
|
||||
ARTIFACT_DIGEST="sha256:a1b2c3d4e5f6..."
|
||||
MANIFEST_HASH="sha256:abc123def456..."
|
||||
FEED_HASH="sha256:feed789feed..."
|
||||
POLICY_HASH="sha256:policy321..."
|
||||
|
||||
# Verify prerequisites
|
||||
if ! command -v stella &> /dev/null; then
|
||||
echo "Error: stella CLI not found. Install from https://stellaops.org/install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Replaying verdict for finding: ${ARTIFACT_DIGEST}"
|
||||
echo "Using manifest: ${MANIFEST_HASH}"
|
||||
|
||||
# Execute replay
|
||||
stella scan replay \
|
||||
--artifact "${ARTIFACT_DIGEST}" \
|
||||
--manifest "${MANIFEST_HASH}" \
|
||||
--feeds "${FEED_HASH}" \
|
||||
--policy "${POLICY_HASH}"
|
||||
|
||||
echo "Replay complete. Verify verdict matches original."
|
||||
```
|
||||
|
||||
### PowerShell Script (replay.ps1)
|
||||
|
||||
```powershell
|
||||
# StellaOps Evidence Bundle Replay Script
|
||||
# Generated: 2025-01-15T10:30:00Z
|
||||
# Finding: f-abc123
|
||||
# CVE: CVE-2024-1234
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# Input hashes for deterministic replay
|
||||
$ArtifactDigest = "sha256:a1b2c3d4e5f6..."
|
||||
$ManifestHash = "sha256:abc123def456..."
|
||||
$FeedHash = "sha256:feed789feed..."
|
||||
$PolicyHash = "sha256:policy321..."
|
||||
|
||||
# Verify prerequisites
|
||||
if (-not (Get-Command stella -ErrorAction SilentlyContinue)) {
|
||||
Write-Error "stella CLI not found. Install from https://stellaops.org/install"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Replaying verdict for finding: $ArtifactDigest"
|
||||
Write-Host "Using manifest: $ManifestHash"
|
||||
|
||||
# Execute replay
|
||||
stella scan replay `
|
||||
--artifact $ArtifactDigest `
|
||||
--manifest $ManifestHash `
|
||||
--feeds $FeedHash `
|
||||
--policy $PolicyHash
|
||||
|
||||
Write-Host "Replay complete. Verify verdict matches original."
|
||||
```
|
||||
|
||||
## README Format
|
||||
|
||||
### Finding README (README.md)
|
||||
|
||||
```markdown
|
||||
# StellaOps Evidence Bundle
|
||||
|
||||
## Overview
|
||||
|
||||
- **Finding ID:** `f-abc123`
|
||||
- **CVE:** `CVE-2024-1234`
|
||||
- **Component:** `pkg:npm/lodash@4.17.15`
|
||||
- **Generated:** 2025-01-15T10:30:00Z
|
||||
|
||||
## Input Hashes for Deterministic Replay
|
||||
|
||||
| Input | Hash |
|
||||
|-------|------|
|
||||
| Artifact Digest | `sha256:a1b2c3d4e5f6...` |
|
||||
| Run Manifest | `sha256:abc123def456...` |
|
||||
| Feed Snapshot | `sha256:feed789feed...` |
|
||||
| Policy | `sha256:policy321...` |
|
||||
|
||||
## Replay Instructions
|
||||
|
||||
### Using Bash
|
||||
```bash
|
||||
chmod +x replay.sh
|
||||
./replay.sh
|
||||
```
|
||||
|
||||
### Using PowerShell
|
||||
```powershell
|
||||
.\replay.ps1
|
||||
```
|
||||
|
||||
## Bundle Contents
|
||||
|
||||
| File | SHA-256 | Size |
|
||||
|------|---------|------|
|
||||
| `sbom.cdx.json` | `abc123...` | 12.3 KB |
|
||||
| `reachability.json` | `789xyz...` | 5.6 KB |
|
||||
| ... | ... | ... |
|
||||
|
||||
## Verification Status
|
||||
|
||||
- **Status:** verified
|
||||
- **Hashes Verified:** ✓
|
||||
- **Attestations Verified:** ✓
|
||||
- **Evidence Complete:** ✓
|
||||
|
||||
---
|
||||
|
||||
*Generated by StellaOps Scanner*
|
||||
```
|
||||
|
||||
## Integrity Verification
|
||||
|
||||
To verify bundle integrity:
|
||||
|
||||
1. **Download with digest header**: The `X-Archive-Digest` response header contains the archive's SHA-256 hash
|
||||
2. **Verify archive hash**: `sha256sum evidence-{findingId}.zip`
|
||||
3. **Verify file hashes**: Compare each file's SHA-256 against `manifest.json`
|
||||
|
||||
Example verification:
|
||||
|
||||
```bash
|
||||
# Verify archive integrity
|
||||
EXPECTED_HASH="abc123..."
|
||||
ACTUAL_HASH=$(sha256sum evidence-f-abc123.zip | cut -d' ' -f1)
|
||||
if [ "$EXPECTED_HASH" = "$ACTUAL_HASH" ]; then
|
||||
echo "Archive integrity verified"
|
||||
else
|
||||
echo "Archive integrity check FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify individual files
|
||||
cd evidence-f-abc123
|
||||
for file in $(jq -r '.files[].path' manifest.json); do
|
||||
expected=$(jq -r ".files[] | select(.path==\"$file\") | .sha256" manifest.json)
|
||||
actual=$(sha256sum "$file" | cut -d' ' -f1)
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo "✓ $file"
|
||||
else
|
||||
echo "✗ $file"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
## Content Types
|
||||
|
||||
| File Type | Content-Type | Description |
|
||||
|-----------|--------------|-------------|
|
||||
| `.json` | `application/json` | JSON data files |
|
||||
| `.cdx.json` | `application/json` | CycloneDX SBOM |
|
||||
| `.dsse.json` | `application/json` | DSSE envelope |
|
||||
| `.sh` | `text/x-shellscript` | Bash script |
|
||||
| `.ps1` | `text/plain` | PowerShell script |
|
||||
| `.md` | `text/markdown` | Markdown documentation |
|
||||
| `.txt` | `text/plain` | Plain text |
|
||||
|
||||
## See Also
|
||||
|
||||
- [stella scan replay Command Reference](../cli/guides/commands/scan-replay.md)
|
||||
- [Deterministic Replay Specification](../replay/DETERMINISTIC_REPLAY.md)
|
||||
- [Unified Evidence Endpoint API](./unified-evidence-endpoint.md)
|
||||
Reference in New Issue
Block a user