up
This commit is contained in:
@@ -0,0 +1,427 @@
|
||||
# Mirror and Offline Kit Strategy
|
||||
|
||||
**Version:** 1.0
|
||||
**Date:** 2025-11-29
|
||||
**Status:** Canonical
|
||||
|
||||
This advisory defines the product rationale, data contracts, and implementation strategy for the Mirror module, covering deterministic thin-bundle assembly, DSSE/TUF signing, time anchoring, and air-gapped distribution.
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
The Mirror module enables **air-gapped deployments** by producing deterministic, cryptographically signed bundles containing advisories, VEX documents, and policy packs. Key capabilities:
|
||||
|
||||
- **Thin Bundle Assembly** - Deterministic tar.gz with sorted entries and fixed timestamps
|
||||
- **DSSE/TUF Signing** - Ed25519 signatures with TUF metadata for key rotation
|
||||
- **Time Anchoring** - Roughtime/RFC3161 tokens for clock-independent freshness
|
||||
- **OCI Distribution** - Registry-compatible layout for container-native workflows
|
||||
- **Offline Verification** - Complete verification without network connectivity
|
||||
|
||||
---
|
||||
|
||||
## 2. Market Drivers
|
||||
|
||||
### 2.1 Target Segments
|
||||
|
||||
| Segment | Offline Requirements | Use Case |
|
||||
|---------|---------------------|----------|
|
||||
| **Defense/Intelligence** | Complete air-gap | Classified networks without internet |
|
||||
| **Critical Infrastructure** | OT network isolation | ICS/SCADA vulnerability management |
|
||||
| **Financial Services** | DMZ-only connectivity | Regulated trading floor systems |
|
||||
| **Healthcare** | Network segmentation | Medical device security scanning |
|
||||
|
||||
### 2.2 Competitive Positioning
|
||||
|
||||
Most vulnerability databases require constant connectivity. Stella Ops differentiates with:
|
||||
- **Cryptographically verifiable offline data** (DSSE + TUF)
|
||||
- **Deterministic bundles** for reproducible deployments
|
||||
- **Time-anchor freshness** without NTP dependency
|
||||
- **OCI-native distribution** for registry mirroring
|
||||
|
||||
---
|
||||
|
||||
## 3. Technical Architecture
|
||||
|
||||
### 3.1 Thin Bundle Layout (v1)
|
||||
|
||||
```
|
||||
mirror-thin-v1.tar.gz
|
||||
├── manifest.json # Bundle metadata, file inventory, hashes
|
||||
├── layers/
|
||||
│ ├── observations.ndjson # Advisory observations
|
||||
│ ├── time-anchor.json # Time token + verification metadata
|
||||
│ └── policies.tar.gz # Policy pack bundle (optional)
|
||||
├── indexes/
|
||||
│ └── observations.index # Linkage index
|
||||
└── oci/ # OCI layout (optional)
|
||||
├── index.json
|
||||
├── oci-layout
|
||||
└── blobs/sha256/...
|
||||
```
|
||||
|
||||
### 3.2 Determinism Rules
|
||||
|
||||
All thin bundles must be **bit-for-bit reproducible**:
|
||||
|
||||
| Property | Rule |
|
||||
|----------|------|
|
||||
| **Tar format** | POSIX with `--sort=name` |
|
||||
| **Owner/Group** | `--owner=0 --group=0` |
|
||||
| **mtime** | `--mtime='1970-01-01'` |
|
||||
| **Gzip** | `--no-name` flag |
|
||||
| **JSON** | Sorted keys, indent=2, trailing newline |
|
||||
| **Hashes** | Lower-case hex, SHA-256 |
|
||||
| **Timestamps** | UTC ISO-8601 (RFC3339) |
|
||||
| **Symlinks** | Not allowed |
|
||||
|
||||
### 3.3 Manifest Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"created": "2025-11-29T00:00:00Z",
|
||||
"bundleId": "mirror-thin-v1-20251129",
|
||||
"generation": 42,
|
||||
"layers": [
|
||||
{
|
||||
"path": "layers/observations.ndjson",
|
||||
"size": 1048576,
|
||||
"digest": "sha256:abc123..."
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
{
|
||||
"name": "observations.index",
|
||||
"digest": "sha256:def456..."
|
||||
}
|
||||
],
|
||||
"hashes": {
|
||||
"tarball_sha256": "sha256:...",
|
||||
"manifest_sha256": "sha256:..."
|
||||
},
|
||||
"timeAnchor": {
|
||||
"generatedAt": "2025-11-29T00:00:00Z",
|
||||
"source": "roughtime",
|
||||
"tokenDigest": "sha256:..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. DSSE/TUF Signing Profile
|
||||
|
||||
### 4.1 DSSE Envelope
|
||||
|
||||
**Payload Type:** `application/vnd.stellaops.mirror+json;version=1`
|
||||
|
||||
**Structure:**
|
||||
|
||||
```json
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.mirror+json;version=1",
|
||||
"payload": "<base64(manifest.json)>",
|
||||
"signatures": [{
|
||||
"keyid": "mirror-root-ed25519-01",
|
||||
"sig": "<base64(Ed25519 signature)>"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
**Header Claims:**
|
||||
- `issuer` - Signing authority identifier
|
||||
- `keyid` - Key reference for verification
|
||||
- `created` - UTC timestamp of signing
|
||||
- `purpose` - Must be `mirror-bundle`
|
||||
|
||||
### 4.2 TUF Metadata Layout
|
||||
|
||||
```
|
||||
tuf/
|
||||
├── root.json # Trust root (long-lived)
|
||||
├── snapshot.json # Metadata versions
|
||||
├── targets.json # Target file mappings
|
||||
├── timestamp.json # Freshness timestamp
|
||||
└── keys/
|
||||
└── mirror-root-ed25519-01.pub
|
||||
```
|
||||
|
||||
**Targets Mapping:**
|
||||
|
||||
```json
|
||||
{
|
||||
"targets": {
|
||||
"mirror-thin-v1.tar.gz": {
|
||||
"length": 10485760,
|
||||
"hashes": {
|
||||
"sha256": "abc123..."
|
||||
}
|
||||
},
|
||||
"mirror-thin-v1.manifest.json": {
|
||||
"length": 2048,
|
||||
"hashes": {
|
||||
"sha256": "def456..."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Key Management
|
||||
|
||||
| Key Type | Lifetime | Storage | Rotation |
|
||||
|----------|----------|---------|----------|
|
||||
| **Root** | 1 year | HSM/offline | Ceremony required |
|
||||
| **Snapshot** | 90 days | Online | Automated |
|
||||
| **Targets** | 90 days | Online | Automated |
|
||||
| **Timestamp** | 1 day | Online | Continuous |
|
||||
|
||||
---
|
||||
|
||||
## 5. Time Anchoring
|
||||
|
||||
### 5.1 Time-Anchor Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"anchorTime": "2025-11-29T00:00:00Z",
|
||||
"source": "roughtime",
|
||||
"format": "roughtime-v1",
|
||||
"tokenDigest": "sha256:...",
|
||||
"signatureFingerprint": "abc123...",
|
||||
"verification": {
|
||||
"status": "passed",
|
||||
"reason": null
|
||||
},
|
||||
"generatedAt": "2025-11-29T00:00:00Z",
|
||||
"sourceClock": "ntp:chrony",
|
||||
"validForSeconds": 86400
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Staleness Calculation
|
||||
|
||||
```
|
||||
stalenessSeconds = now_utc - generatedAt
|
||||
isStale = stalenessSeconds > (validForSeconds + 5s_tolerance)
|
||||
```
|
||||
|
||||
**Default validity:** 24 hours (86400 seconds)
|
||||
|
||||
### 5.3 Trust Roots
|
||||
|
||||
Trust roots for time verification stored in offline-friendly bundle:
|
||||
|
||||
```json
|
||||
{
|
||||
"roughtime": [
|
||||
{
|
||||
"name": "cloudflare",
|
||||
"publicKey": "...",
|
||||
"address": "roughtime.cloudflare.com:2002"
|
||||
}
|
||||
],
|
||||
"rfc3161": [
|
||||
{
|
||||
"name": "digicert",
|
||||
"url": "http://timestamp.digicert.com",
|
||||
"certificate": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Implementation Strategy
|
||||
|
||||
### 6.1 Phase 1: Thin Bundle Assembly (Complete)
|
||||
|
||||
- [x] Deterministic tarball assembler (`make-thin-v1.sh`)
|
||||
- [x] Manifest generation with sorted keys
|
||||
- [x] OCI layout generation
|
||||
- [x] Verification scripts (`verify_thin_bundle.py`)
|
||||
|
||||
### 6.2 Phase 2: DSSE/TUF Signing (In Progress)
|
||||
|
||||
- [x] DSSE envelope generation with Ed25519
|
||||
- [x] TUF metadata structure
|
||||
- [ ] Production key provisioning (blocked on CI secret)
|
||||
- [ ] Automated rotation pipeline
|
||||
|
||||
### 6.3 Phase 3: Time Anchoring (In Progress)
|
||||
|
||||
- [x] Time-anchor schema definition
|
||||
- [x] Contract for `generatedAt`, `validForSeconds` fields
|
||||
- [ ] Production Roughtime/RFC3161 integration
|
||||
- [ ] Trust roots provisioning
|
||||
|
||||
### 6.4 Phase 4: Distribution Integration (Planned)
|
||||
|
||||
- [ ] Export Center mirror profile automation
|
||||
- [ ] Orchestrator `mirror.ready` event emission
|
||||
- [ ] CLI `stella mirror create|verify|status` commands
|
||||
- [ ] OCI registry push/pull workflows
|
||||
|
||||
---
|
||||
|
||||
## 7. API Surface
|
||||
|
||||
### 7.1 Mirror APIs
|
||||
|
||||
| Endpoint | Method | Scope | Description |
|
||||
|----------|--------|-------|-------------|
|
||||
| `/mirror/bundles` | GET | `mirror:read` | List mirror bundles |
|
||||
| `/mirror/bundles/{id}` | GET | `mirror:read` | Get bundle metadata |
|
||||
| `/mirror/bundles/{id}/download` | GET | `mirror:read` | Download thin bundle |
|
||||
| `/mirror/bundles` | POST | `mirror:create` | Create new mirror bundle |
|
||||
| `/mirror/verify` | POST | `mirror:read` | Verify bundle integrity |
|
||||
|
||||
### 7.2 Orchestrator Events
|
||||
|
||||
**Event:** `mirror.ready`
|
||||
|
||||
```json
|
||||
{
|
||||
"bundleId": "mirror-thin-v1-20251129",
|
||||
"generation": 42,
|
||||
"generatedAt": "2025-11-29T00:00:00Z",
|
||||
"manifestDigest": "sha256:...",
|
||||
"dsseDigest": "sha256:...",
|
||||
"location": "s3://mirrors/thin/v1/...",
|
||||
"rekorUUID": "..."
|
||||
}
|
||||
```
|
||||
|
||||
**Semantics:** At-least-once delivery; consumers de-dup by `(bundleId, generation)`.
|
||||
|
||||
### 7.3 CLI Commands
|
||||
|
||||
```bash
|
||||
# Create mirror bundle
|
||||
stella mirror create --output mirror-thin-v1.tar.gz
|
||||
|
||||
# Verify bundle integrity
|
||||
stella mirror verify mirror-thin-v1.tar.gz
|
||||
|
||||
# Check bundle status
|
||||
stella mirror status --bundle-id mirror-thin-v1-20251129
|
||||
|
||||
# Import bundle into air-gapped installation
|
||||
stella airgap import mirror-thin-v1.tar.gz --describe
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Offline Kit Integration
|
||||
|
||||
### 8.1 Offline Kit Structure
|
||||
|
||||
```
|
||||
offline-kit/
|
||||
├── mirrors/
|
||||
│ ├── mirror-thin-v1.tar.gz # Advisory/VEX data
|
||||
│ ├── mirror-thin-v1.manifest.json
|
||||
│ └── mirror-thin-v1.dsse.json
|
||||
├── evidence/
|
||||
│ └── evidence-bundle-*.tar.gz # Evidence bundles
|
||||
├── policies/
|
||||
│ └── policy-pack-*.tar.gz # Policy packs
|
||||
├── trust/
|
||||
│ ├── tuf/ # TUF metadata
|
||||
│ └── time-anchors.json # Time trust roots
|
||||
└── MANIFEST.json # Kit manifest with hashes
|
||||
```
|
||||
|
||||
### 8.2 Import Workflow
|
||||
|
||||
1. **Verify MANIFEST.json** signature against bundled TUF root
|
||||
2. **Validate each artifact** hash matches manifest
|
||||
3. **Check time anchor freshness** against configured tolerance
|
||||
4. **Import to local stores** (Concelier, Excititor, Evidence Locker)
|
||||
5. **Record import event** with provenance in Timeline
|
||||
|
||||
---
|
||||
|
||||
## 9. Verification Workflow
|
||||
|
||||
### 9.1 Online Verification
|
||||
|
||||
1. Fetch bundle from registry/export center
|
||||
2. Verify DSSE signature against JWKS
|
||||
3. Validate TUF metadata chain
|
||||
4. Check Rekor transparency log (if present)
|
||||
5. Verify time anchor freshness
|
||||
|
||||
### 9.2 Offline Verification
|
||||
|
||||
1. Extract bundle and TUF metadata
|
||||
2. Verify DSSE signature against bundled public key
|
||||
3. Validate all file hashes match manifest
|
||||
4. Check time anchor against local clock + tolerance
|
||||
5. Record verification result in local audit log
|
||||
|
||||
---
|
||||
|
||||
## 10. Security Considerations
|
||||
|
||||
### 10.1 Key Protection
|
||||
|
||||
- Root keys stored in HSM or offline cold storage
|
||||
- Online keys rotated automatically per TUF policy
|
||||
- Key ceremonies documented and audited
|
||||
|
||||
### 10.2 Rollback Protection
|
||||
|
||||
- TUF timestamp/snapshot prevent rollback attacks
|
||||
- Generation numbers monotonically increasing
|
||||
- Stale bundles rejected based on time anchor
|
||||
|
||||
### 10.3 Tampering Detection
|
||||
|
||||
- DSSE signature covers entire manifest
|
||||
- Each file has individual hash verification
|
||||
- Merkle tree optional for large bundles
|
||||
|
||||
---
|
||||
|
||||
## 11. Related Documentation
|
||||
|
||||
| Resource | Location |
|
||||
|----------|----------|
|
||||
| Mirror module docs | `docs/modules/mirror/` |
|
||||
| DSSE/TUF profile | `docs/modules/mirror/dsse-tuf-profile.md` |
|
||||
| Thin bundle spec | `docs/modules/mirror/thin-bundle-assembler.md` |
|
||||
| Time-anchor schema | `docs/airgap/time-anchor-schema.json` |
|
||||
| Signing runbook | `docs/modules/mirror/signing-runbook.md` |
|
||||
|
||||
---
|
||||
|
||||
## 12. Sprint Mapping
|
||||
|
||||
- **Primary Sprint:** SPRINT_0125_0001_0001 (Mirror Bundles)
|
||||
- **Coordination:** SPRINT_0150_0001_0001 (DSSE/Time Anchors)
|
||||
|
||||
**Key Task IDs:**
|
||||
- `MIRROR-CRT-56-001` - Deterministic assembler (DONE)
|
||||
- `MIRROR-CRT-56-002` - DSSE/TUF signing (BLOCKED - CI key needed)
|
||||
- `MIRROR-CRT-57-001` - OCI layout generation (DONE)
|
||||
- `MIRROR-CRT-57-002` - Time-anchor embedding (PARTIAL)
|
||||
- `CLI-AIRGAP-56-001` - CLI mirror commands (BLOCKED)
|
||||
|
||||
---
|
||||
|
||||
## 13. Success Metrics
|
||||
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| Bundle hash reproducibility | 100% (bit-identical) |
|
||||
| DSSE verification success | 100% for valid bundles |
|
||||
| Time anchor freshness | < 24 hours default |
|
||||
| Offline import success | Works without network |
|
||||
| TUF metadata validation | Full chain verified |
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 2025-11-29*
|
||||
Reference in New Issue
Block a user