Files
git.stella-ops.org/docs/modules/airgap/architecture.md
StellaOps Bot e6c47c8f50 save progress
2025-12-28 23:49:56 +02:00

349 lines
10 KiB
Markdown

# component_architecture_airgap.md - **Stella Ops AirGap** (2025Q4)
> Air-gapped deployment controller, importer, and time anchor services.
> **Scope.** Implementation-ready architecture for **AirGap**: the controller, importer, and time anchor subsystems enabling StellaOps operation in disconnected/air-gapped environments with sealed-mode state management.
---
## 0) Mission & boundaries
**Mission.** Enable **fully offline, air-gapped operation** of StellaOps with sealed-mode state management, bundle-based updates, and cryptographic time anchors for staleness detection.
**Boundaries.**
* AirGap **does not** connect to external networks in sealed mode.
* AirGap **does not** generate vulnerability data. It imports pre-packaged bundles.
* Bundle verification is **mandatory**. Unsigned or tampered bundles are rejected.
* Time anchors are **cryptographically verified** using Roughtime or RFC3161.
---
## 1) Solution & project layout
```
src/AirGap/
├─ StellaOps.AirGap.Controller/ # Seal/unseal state machine, status APIs
│ ├─ Services/
│ │ ├─ ISealingController.cs # Sealing state interface
│ │ ├─ SealingController.cs # State machine implementation
│ │ └─ StatusService.cs # Health and status endpoints
│ └─ Models/
│ ├─ SealState.cs # sealed | unsealed | transitioning
│ └─ SealTransition.cs # Transition metadata
├─ StellaOps.AirGap.Importer/ # Bundle verification and import
│ ├─ Services/
│ │ ├─ IBundleVerifier.cs # DSSE/TUF verification
│ │ ├─ BundleVerifier.cs # Verification implementation
│ │ ├─ ICatalogImporter.cs # Catalog update interface
│ │ └─ CatalogImporter.cs # Import orchestration
│ └─ Models/
│ ├─ ImportBundle.cs # Bundle metadata
│ └─ ImportResult.cs # Import outcome
├─ StellaOps.AirGap.Time/ # Time anchor verification
│ ├─ Services/
│ │ ├─ ITimeAnchorService.cs # Time anchor interface
│ │ ├─ RoughtimeAnchor.cs # Roughtime implementation
│ │ └─ Rfc3161Anchor.cs # RFC3161 timestamp
│ └─ Models/
│ ├─ TimeAnchor.cs # Anchor record
│ └─ StalenessResult.cs # Staleness calculation
├─ StellaOps.AirGap.Policy/ # Air-gap specific policy rules
│ ├─ StellaOps.AirGap.Policy/
│ ├─ StellaOps.AirGap.Policy.Analyzers/
│ └─ StellaOps.AirGap.Policy.Tests/
├─ __Libraries/
│ ├─ StellaOps.AirGap.Bundle/ # Bundle format and parsing
│ └─ StellaOps.AirGap.Persistence/ # State persistence
├─ __Tests/ # Test projects
├─ scripts/ # Operational scripts
└─ AGENTS.md # Guild charter
```
---
## 2) External dependencies
* **PostgreSQL** - State persistence, import history
* **Authority** - Scope enforcement (`airgap:seal`, `airgap:status:read`)
* **Cryptography** - Bundle signature verification
* **Object storage** - Bundle staging and quarantine
---
## 3) Contracts & data model
### 3.1 Seal State
```csharp
public enum SealState
{
Unsealed, // Normal operation, network allowed
Transitioning, // Sealing or unsealing in progress
Sealed // Air-gapped, no network egress
}
public sealed record SealStatus
{
public required SealState State { get; init; }
public required DateTimeOffset LastTransition { get; init; }
public required string TransitionedBy { get; init; }
public DateTimeOffset? SealedSince { get; init; }
public TimeAnchor? LastTimeAnchor { get; init; }
}
```
### 3.2 Import Bundle
```json
{
"bundleId": "airgap-2025-01-15-abc123",
"bundleType": "advisory-update",
"version": "2025.01.15.001",
"createdAt": "2025-01-15T10:30:00Z",
"contents": [
{
"type": "concelier-snapshot",
"digest": "sha256:abc123...",
"path": "data/concelier-2025-01-15.tar.zst"
},
{
"type": "trivy-db",
"digest": "sha256:def456...",
"path": "data/trivy-db-2025-01-15.tar.gz"
}
],
"signature": {
"keyId": "sha256:sigkey...",
"algorithm": "ecdsa-p256",
"value": "base64..."
},
"timeAnchor": {
"source": "roughtime",
"timestamp": "2025-01-15T10:25:00Z",
"proof": "base64..."
}
}
```
### 3.3 Time Anchor
```csharp
public sealed record TimeAnchor
{
public required string Source { get; init; } // roughtime, rfc3161
public required DateTimeOffset Timestamp { get; init; }
public required byte[] Proof { get; init; } // Cryptographic proof
public required string[] Servers { get; init; } // Servers used
public required bool Verified { get; init; }
}
public sealed record StalenessResult
{
public required TimeSpan Age { get; init; }
public required bool IsStale { get; init; }
public required TimeSpan StalenessThreshold { get; init; }
public string? Warning { get; init; }
}
```
---
## 4) REST API (Controller + Importer)
All under `/api/v1/airgap`. Auth: **OpTok** with airgap scopes.
### Controller APIs
```
GET /status → { state, lastTransition, timeAnchor }
POST /seal → { transitionId, status: "transitioning" }
POST /unseal → { transitionId, status: "transitioning" }
GET /transitions/{id} → { transition details }
```
### Importer APIs
```
POST /bundles/upload multipart → { bundleId, status: "pending" }
POST /bundles/{id}/verify → { valid: bool, details }
POST /bundles/{id}/import → { importId, status: "importing" }
GET /bundles/{id}/status → { status, progress, errors }
GET /bundles → { bundles: BundleSummary[] }
```
### Time APIs
```
GET /time/anchor → { anchor: TimeAnchor, staleness }
POST /time/anchor { source, proof } → { anchor, verified }
GET /time/staleness → { staleness: StalenessResult }
```
---
## 5) Configuration (YAML)
```yaml
AirGap:
Controller:
InitialState: "unsealed"
TransitionTimeoutSeconds: 300
RequireApproval: true
Importer:
StagingPath: "/data/airgap/staging"
QuarantinePath: "/data/airgap/quarantine"
MaxBundleSizeMb: 10240
TrustRoots:
- "sha256:abc123..." # StellaOps signing key
AllowedBundleTypes:
- "advisory-update"
- "trivy-db"
- "policy-pack"
Time:
StalenessThresholdHours: 168 # 7 days
RoughtimeServers:
- "roughtime.cloudflare.com"
- "roughtime.google.com"
Rfc3161Servers:
- "http://timestamp.digicert.com"
RequireMultipleServers: true
MinServerQuorum: 2
Quarantine:
TtlDays: 30
MaxQuotaMb: 51200
Postgres:
ConnectionString: "Host=postgres;Database=airgap;..."
```
---
## 6) Sealing State Machine
```
┌──────────────┐
│ Unsealed │
└──────┬───────┘
│ seal()
┌──────────────┐
│ Transitioning│
└──────┬───────┘
│ complete
┌──────────────┐
│ Sealed │
└──────┬───────┘
│ unseal()
┌──────────────┐
│ Transitioning│
└──────┬───────┘
│ complete
┌──────────────┐
│ Unsealed │
└──────────────┘
```
### Transition Actions
**Seal transition:**
1. Verify pending work is complete
2. Capture final time anchor
3. Disable network egress
4. Update state to Sealed
**Unseal transition:**
1. Verify network connectivity
2. Refresh time anchor
3. Enable network egress
4. Update state to Unsealed
---
## 7) Bundle Import Flow
```
1. Upload bundle to staging
└─ Validate manifest structure
2. Verify bundle
├─ Check signature against trust roots
├─ Verify content digests
└─ Validate time anchor
3. Import bundle
├─ Extract contents
├─ Update target catalogs (Concelier, Trivy, etc.)
└─ Record import in history
4. Cleanup or quarantine
├─ Success: Remove from staging
└─ Failure: Move to quarantine with TTL
```
---
## 8) Security & compliance
* **Signature verification**: All bundles must be signed
* **Trust roots**: Configurable trust root keys
* **Quarantine**: Failed imports isolated with TTL
* **Audit trail**: All imports and state changes logged
* **Scope enforcement**: Authority scopes for all operations
* **Rollback prevention**: Version monotonicity enforced
---
## 9) Performance targets
* **Seal/unseal transition**: < 30s
* **Bundle verification**: < 10s for 1GB bundle
* **Bundle import**: < 60s for typical advisory update
* **Time anchor verification**: < 5s
---
## 10) Observability
**Metrics:**
* `airgap.state{state=sealed|unsealed|transitioning}`
* `airgap.bundles.imported_total{type,result}`
* `airgap.bundles.quarantined_total{reason}`
* `airgap.time.staleness_seconds`
* `airgap.time.anchor_age_seconds`
**Tracing:** Spans for transitions, imports, verifications.
---
## 11) Testing matrix
* **Seal/unseal tests**: State machine transitions
* **Bundle tests**: Verification and import flows
* **Quarantine tests**: Failed import handling
* **Time tests**: Staleness calculations, anchor verification
* **Integration tests**: Full offline workflow simulation
---
## Related Documentation
* Evidence reconciliation: `./evidence-reconciliation.md`
* Exporter coordination: `./exporter-cli-coordination.md`
* Mirror DSSE plan: `./mirror-dsse-plan.md`
* Offline Kit: `../../24_OFFLINE_KIT.md`
* Time anchor schema: `../../airgap/time-anchor-schema.md`