Skip to content

Implement policy-based runtime capsule issuance#1485

Open
WillEastbury wants to merge 2 commits intomainfrom
issue-1430-runtime-capsule-policy
Open

Implement policy-based runtime capsule issuance#1485
WillEastbury wants to merge 2 commits intomainfrom
issue-1430-runtime-capsule-policy

Conversation

@WillEastbury
Copy link
Owner

Summary

Implements GET /api/runtime/capsule/{nodeId} — a policy-gated endpoint that controls whether a deployment node receives a runtime capsule (encryption key + signed envelope) needed to start BMW.

Policy Pipeline (8 stages)

  1. Bearer auth — SHA256 secret hash verification
  2. Node existence — 404-safe lookup by nodeId
  3. Status check — reject revoked/disabled nodes
  4. Fingerprint verification — device hardware fingerprint match
  5. Telemetry behaviour — detect abrupt stops (unclean shutdown + recent telemetry)
  6. Network policy — risk scoring: IP change (+20), ASN change (+40), region change (+50), abrupt stop (+80). Score ≥80 → auto-quarantine
  7. HKDF key derivation — per-node runtime key from cluster master key + nodeId/fingerprint/version
  8. Capsule envelope — capsuleId, runtimeKey (base64), HMAC-SHA256 signature, 24h expiry

Changes

  • DeploymentNode.cs — Added 8 policy fields: Fingerprint, Status enum (Active/Revoked/Quarantined), LastTelemetryUtc, LastShutdownClean, LastKnownIp/Asn/Region, LastCapsuleIssuedUtc
  • Models.cs — Added CapsuleRequest, CapsuleDenialReason enum, CapsulePolicyResult
  • RouteRegistrationExtensions.cs — Capsule endpoint + WriteCapsuleDenied helper

Denial Responses

{"denied":true,"reason":"NODE_REVOKED"}
{"denied":true,"reason":"NETWORK_POLICY_VIOLATION","riskScore":90}

Closes #1430

WillEastbury and others added 2 commits March 16, 2026 09:19
Add GET /api/runtime/capsule/{nodeId} endpoint with multi-stage policy:

1. Identity verification: Bearer token auth + node existence check
2. Status check: reject revoked/disabled nodes
3. Fingerprint verification: compare device fingerprint header
4. Telemetry behaviour: detect abrupt stops (unclean shutdown + recent telemetry)
5. Network policy: risk scoring (IP +20, ASN +40, region +50, abrupt stop +80)
   Nodes scoring >=80 auto-quarantined
6. HKDF key derivation: per-node runtime key from cluster master
7. Capsule envelope: capsuleId, runtimeKey, HMAC-SHA256 signature, 24h expiry
8. Node state update: IP/ASN/region/capsule timestamp persisted

Extended DeploymentNode with policy fields. Added capsule models.

Closes #1430

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace string.Equals with CryptographicOperations.FixedTimeEquals
  for bearer token validation (prevents timing side-channel)
- Make WriteCapsuleDenied async and await all 7 call sites
- Cache HKDF master key at startup instead of reading /etc/machine-id
  on every request (eliminates file I/O on hot path)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Policy-Based Runtime Capsule Issuance for BMW Nodes

1 participant