Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Introduced `SbomService` tasks documentation. - Updated `StellaOps.sln` to include new projects: `StellaOps.AirGap.Time` and `StellaOps.AirGap.Importer`. - Added unit tests for `BundleImportPlanner`, `DsseVerifier`, `ImportValidator`, and other components in the `StellaOps.AirGap.Importer.Tests` namespace. - Implemented `InMemoryBundleRepositories` for testing bundle catalog and item repositories. - Created `MerkleRootCalculator`, `RootRotationPolicy`, and `TufMetadataValidator` tests. - Developed `StalenessCalculator` and `TimeAnchorLoader` tests in the `StellaOps.AirGap.Time.Tests` namespace. - Added `fetch-sbomservice-deps.sh` script for offline dependency fetching.
3.2 KiB
3.2 KiB
Air-Gapped Time Anchors & Staleness Budgets
Audience: AirGap Time/Controller/Policy guilds, DevOps
Purpose: Document how air-gapped installations maintain trusted time anchors, compute staleness windows, and expose drift telemetry.
1. Overview
Air-gapped clusters cannot contact external NTP servers. StellaOps distributes signed time anchor tokens alongside mirror bundles so services can reason about freshness and seal state without external clocks.
Key goals:
- Provide deterministic time anchors signed by the mirror authority.
- Track drift and staleness budgets for scanner reports, advisories, and runtime evidence.
- Surface warnings to operators (UI/CLI/Notifier) before anchors expire.
2. Components
| Component | Responsibility |
|---|---|
| AirGap Controller | Stores the active time_anchor token and enforces sealed/unsealed transitions. |
| AirGap Time service | Parses anchor bundles, validates signatures, records monotonic offsets, and exposes drift metrics. |
| Scheduler & Policy Engine | Query the time service to gate scheduled runs and evidence evaluation. |
| UI / Notifier | Display remaining budget and raise alerts when thresholds are crossed. |
3. Time Anchor Tokens
- Distributed as part of mirror/offline bundles (
airgap/time-anchor.json). - Signed with mirror key; includes issuance time, validity window, and monotonic counter.
- Validation steps:
- Verify detached signature.
- Compare bundle counter to previously applied anchors.
- Persist anchor with checksum for audit.
4. Staleness Budgets
Each tenant/configuration defines budgets:
- Advisory freshness – maximum age of advisory/VEX data before rescans are required.
- Scanner evidence – acceptable drift between last scan and current anchor.
- Runtime posture – tolerated drift before Notifier raises incidents.
AirGap Time calculates drift = now(monotonic) - anchor.issued_at and exposes:
/api/v1/time/status– current anchor metadata, drift, remaining budget./api/v1/time/metrics– Prometheus counters (airgap_anchor_drift_seconds,airgap_anchor_expiry_seconds).
5. Operator Workflow
- Import new mirror bundle (includes time anchor).
- AirGap Time validates and stores the anchor; Controller records audit entry.
- Services subscribe to change events and recompute drift.
- UI displays badge (green/amber/red) based on thresholds.
- Notifier sends alerts when drift exceeds warning or expiry limits.
6. Implementation Notes
- Use
IAirGapTimeStorefor persistence; default implementation relies on Mongo with tenant partitioning. - Ensure deterministic JSON serialization (UTC ISO-8601 timestamps, sorted keys).
- Test vectors located under
src/AirGap/StellaOps.AirGap.Time/fixtures/. - For offline testing, simulate monotonic clock via
ITestClockto avoid system clock drift in CI. - Staleness calculations use
StalenessCalculator+StalenessBudget/StalenessEvaluation(seesrc/AirGap/StellaOps.AirGap.Time/Servicesand.Models); warning/breach thresholds must be non-negative and warning ≤ breach.
7. References
docs/airgap/airgap-mode.mdsrc/AirGap/StellaOps.AirGap.Timesrc/AirGap/StellaOps.AirGap.Controllersrc/AirGap/StellaOps.AirGap.Policy