audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories

This commit is contained in:
master
2026-01-07 18:49:59 +02:00
parent 04ec098046
commit 608a7f85c0
866 changed files with 56323 additions and 6231 deletions

View File

@@ -0,0 +1,354 @@
# Evidence Bundle Export Format Specification
> **Version:** 1.0.0
> **Status:** FINAL
> **Sprint Reference:** [SPRINT_20260106_003_003](../../../docs/implplan/SPRINT_20260106_003_003_EVIDENCE_export_bundle.md)
## Overview
This document specifies the standard export format for StellaOps evidence bundles. The export format enables offline verification of software supply chain artifacts including SBOMs, VEX statements, attestations, and policy verdicts.
## Export Archive Format
### Filename Convention
```
evidence-bundle-<bundle-id>.tar.gz
```
Where `<bundle-id>` follows the pattern: `eb-<YYYY-MM-DD>-<unique-suffix>`
Example: `evidence-bundle-eb-2026-01-06-abc123.tar.gz`
### Compression
- **Format:** gzip-compressed tar archive
- **Compression level:** Configurable (1-9, default: 6)
- **Determinism:** Fixed gzip header timestamp (`2026-01-01T00:00:00Z`)
- **Permissions:** All files `0644`, directories `0755`, uid/gid `0:0`
## Directory Structure
```
evidence-bundle-<id>/
├── manifest.json # Bundle manifest with all artifact refs
├── metadata.json # Bundle metadata (provenance, timestamps)
├── README.md # Human-readable verification instructions
├── verify.sh # Bash verification script (POSIX-compliant)
├── verify.ps1 # PowerShell verification script
├── checksums.sha256 # BSD-format SHA256 checksums
├── keys/
│ ├── signing-key-001.pem # Public key(s) for DSSE verification
│ ├── signing-key-002.pem # Additional keys (multi-signature)
│ └── trust-bundle.pem # CA chain (if applicable)
├── sboms/
│ ├── image.cdx.json # Aggregated CycloneDX SBOM
│ ├── image.spdx.json # Aggregated SPDX SBOM
│ └── layers/
│ ├── <layer-digest>.cdx.json # Per-layer CycloneDX
│ └── <layer-digest>.spdx.json # Per-layer SPDX
├── vex/
│ ├── statements/
│ │ └── <statement-id>.openvex.json
│ └── consensus/
│ └── image-consensus.json # VEX consensus result
├── attestations/
│ ├── sbom.dsse.json # SBOM attestation envelope
│ ├── vex.dsse.json # VEX attestation envelope
│ ├── policy.dsse.json # Policy verdict attestation
│ └── rekor-proofs/
│ └── <uuid>.proof.json # Rekor inclusion proofs
├── findings/
│ ├── scan-results.json # Vulnerability findings
│ └── gate-results.json # VEX gate decisions
└── audit/
└── timeline.ndjson # Audit event timeline
```
## Core Artifacts
### manifest.json
The manifest provides a complete inventory of all artifacts in the bundle.
```json
{
"manifestVersion": "1.0.0",
"bundleId": "eb-2026-01-06-abc123",
"createdAt": "2026-01-06T10:30:00.000000Z",
"subject": {
"type": "container-image",
"digest": "sha256:abcdef1234567890...",
"name": "registry.example.com/app:v1.2.3"
},
"artifacts": [
{
"path": "sboms/image.cdx.json",
"type": "sbom",
"format": "cyclonedx-1.7",
"digest": "sha256:...",
"size": 45678
},
{
"path": "attestations/sbom.dsse.json",
"type": "attestation",
"format": "dsse-v1",
"predicateType": "StellaOps.SBOMAttestation@1",
"digest": "sha256:...",
"size": 12345,
"signedBy": ["sha256:keyabc..."]
}
],
"verification": {
"merkleRoot": "sha256:...",
"algorithm": "sha256",
"checksumFile": "checksums.sha256"
}
}
```
### metadata.json
Provides provenance and chain information.
```json
{
"bundleId": "eb-2026-01-06-abc123",
"exportedAt": "2026-01-06T10:35:00.000000Z",
"exportedBy": "stella evidence export",
"exportVersion": "2026.04",
"provenance": {
"tenantId": "tenant-xyz",
"scanId": "scan-abc123",
"pipelineId": "pipeline-def456",
"sourceRepository": "https://github.com/example/app",
"sourceCommit": "abc123def456..."
},
"chainInfo": {
"previousBundleId": "eb-2026-01-05-xyz789",
"sequenceNumber": 42
},
"transparency": {
"rekorLogUrl": "https://rekor.sigstore.dev",
"rekorEntryUuids": ["uuid1", "uuid2"]
}
}
```
### checksums.sha256
BSD-format SHA256 checksums for all artifacts:
```
SHA256 (manifest.json) = abc123...
SHA256 (metadata.json) = def456...
SHA256 (sboms/image.cdx.json) = 789abc...
SHA256 (attestations/sbom.dsse.json) = cde012...
```
## Verification Scripts
### verify.sh (Bash)
POSIX-compliant bash script for Unix/Linux/macOS verification:
```bash
#!/bin/bash
set -euo pipefail
BUNDLE_DIR="$(cd "$(dirname "$0")" && pwd)"
MANIFEST="$BUNDLE_DIR/manifest.json"
CHECKSUMS="$BUNDLE_DIR/checksums.sha256"
echo "=== StellaOps Evidence Bundle Verification ==="
echo "Bundle: $(basename "$BUNDLE_DIR")"
echo ""
# Step 1: Verify checksums
echo "[1/4] Verifying artifact checksums..."
cd "$BUNDLE_DIR"
sha256sum -c "$CHECKSUMS" --quiet
echo " OK: All checksums match"
# Step 2: Verify Merkle root
echo "[2/4] Verifying Merkle root..."
COMPUTED_ROOT=$(compute-merkle-root "$CHECKSUMS")
EXPECTED_ROOT=$(jq -r '.verification.merkleRoot' "$MANIFEST")
if [ "$COMPUTED_ROOT" = "$EXPECTED_ROOT" ]; then
echo " OK: Merkle root verified"
else
echo " FAIL: Merkle root mismatch"
exit 1
fi
# Step 3: Verify DSSE signatures
echo "[3/4] Verifying attestation signatures..."
for dsse in "$BUNDLE_DIR"/attestations/*.dsse.json; do
verify-dsse "$dsse" --keys "$BUNDLE_DIR/keys/"
echo " OK: $(basename "$dsse")"
done
# Step 4: Verify Rekor proofs (if online)
echo "[4/4] Verifying Rekor proofs..."
if [ "${OFFLINE:-false}" = "true" ]; then
echo " SKIP: Offline mode, Rekor verification skipped"
else
for proof in "$BUNDLE_DIR"/attestations/rekor-proofs/*.proof.json; do
verify-rekor-proof "$proof"
echo " OK: $(basename "$proof")"
done
fi
echo ""
echo "=== Verification Complete: PASSED ==="
```
### verify.ps1 (PowerShell)
Windows PowerShell verification script:
```powershell
#Requires -Version 5.1
$ErrorActionPreference = 'Stop'
$BundleDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Manifest = Join-Path $BundleDir 'manifest.json'
$Checksums = Join-Path $BundleDir 'checksums.sha256'
Write-Host "=== StellaOps Evidence Bundle Verification ===" -ForegroundColor Cyan
Write-Host "Bundle: $(Split-Path -Leaf $BundleDir)"
Write-Host ""
# Step 1: Verify checksums
Write-Host "[1/4] Verifying artifact checksums..." -ForegroundColor Yellow
Push-Location $BundleDir
try {
Get-Content $Checksums | ForEach-Object {
if ($_ -match 'SHA256 \((.+)\) = (.+)') {
$File = $Matches[1]
$Expected = $Matches[2]
$Actual = (Get-FileHash -Path $File -Algorithm SHA256).Hash.ToLower()
if ($Actual -ne $Expected) {
throw "Checksum mismatch: $File"
}
}
}
Write-Host " OK: All checksums match" -ForegroundColor Green
} finally {
Pop-Location
}
# Step 2-4: Continue verification...
Write-Host ""
Write-Host "=== Verification Complete: PASSED ===" -ForegroundColor Green
```
## Determinism Requirements
### Timestamp Handling
- All timestamps MUST be UTC ISO-8601 with microsecond precision
- Format: `YYYY-MM-DDTHH:MM:SS.ffffffZ`
- Archive metadata timestamps are fixed for reproducibility
### Ordering
- Manifest artifacts: sorted lexicographically by `path`
- Checksum entries: sorted lexicographically by filename
- JSON object keys: sorted lexicographically (RFC 8785)
- NDJSON records: sorted by primary key (e.g., `observationId`)
### Hash Computation
- Algorithm: SHA-256 (lowercase hex)
- Input: raw file bytes (no BOM, LF line endings)
- Merkle tree: RFC 6962 compliant binary Merkle tree
## Artifact Types
### SBOMs
| Format | File Extension | MIME Type |
|--------|---------------|-----------|
| CycloneDX 1.7 | `.cdx.json` | `application/vnd.cyclonedx+json` |
| SPDX 3.0.1 | `.spdx.json` | `application/spdx+json` |
### Attestations
| Type | Predicate Type | File Pattern |
|------|---------------|--------------|
| SBOM | `StellaOps.SBOMAttestation@1` | `sbom.dsse.json` |
| VEX | `StellaOps.VEXAttestation@1` | `vex.dsse.json` |
| Policy | `StellaOps.PolicyEvaluation@1` | `policy.dsse.json` |
| Gate | `StellaOps.VexGate@1` | `gate.dsse.json` |
### VEX Statements
- Format: OpenVEX 0.2.0+
- File extension: `.openvex.json`
- Location: `vex/statements/`
## Export Options
### CLI Command
```bash
# Basic export
stella evidence export --bundle <bundle-id> --output ./audit-bundle.tar.gz
# With options
stella evidence export --bundle <bundle-id> \
--output ./bundle.tar.gz \
--include-layers \
--include-rekor-proofs \
--compression 9
# Verify exported bundle
stella evidence verify ./audit-bundle.tar.gz
# Verify offline (skip Rekor)
stella evidence verify ./audit-bundle.tar.gz --offline
```
### API Endpoint
```http
POST /api/v1/bundles/{bundleId}/export
Content-Type: application/json
{
"format": "tar.gz",
"compression": "gzip",
"compressionLevel": 6,
"includeRekorProofs": true,
"includeLayerSboms": true
}
```
## Offline Verification
For air-gapped environments:
1. Transfer `evidence-bundle-<id>.tar.gz` to isolated system
2. Extract archive: `tar -xzf evidence-bundle-<id>.tar.gz`
3. Run verification: `./verify.sh` (Unix) or `.\verify.ps1` (Windows)
4. Pass `OFFLINE=true` to skip Rekor verification: `OFFLINE=true ./verify.sh`
## Compatibility
- **StellaOps CLI:** 2026.04+
- **Export Library:** StellaOps.EvidenceLocker.Export 1.0.0+
- **Verify scripts:** bash 4.0+ / PowerShell 5.1+
## Related Documentation
- [Bundle Packaging](bundle-packaging.md) - Internal bundle structure
- [Evidence Bundle v1](evidence-bundle-v1.md) - Core bundle contract
- [Verify Offline](verify-offline.md) - Offline verification procedures
- [Attestation Contract](attestation-contract.md) - DSSE envelope format
## Change Log
| Date | Version | Author | Description |
|------|---------|--------|-------------|
| 2026-01-07 | 1.0.0 | StellaOps | Initial specification for Sprint 003_003 |