Context
Satellites send heartbeat/status reports to Ground Control via POST /satellites/sync. This endpoint should validate that requests come from legitimate registered satellites.
Current State
Satellite side (internal/state/reporting_process.go:120-154):
- Sends POST to
/satellites/sync with JSON body
- Only sets
Content-Type: application/json header
- No authentication credentials sent
GC side (ground-control/internal/server/satellite_handlers.go:358):
- Looks up satellite by
name field from request body
- If satellite exists in DB, processes the request
- No credential validation
Security Issue: Anyone who knows a satellite name can impersonate it and send fake status reports. The route is public (not under protected subrouter).
Expected Behavior
Option A: Robot Account Credentials (ZTR)
- Satellite includes robot account credentials (from ZTR) in Authorization header
- GC validates credentials against stored robot account for that satellite
- Return 401 if credentials invalid or don't match satellite
Option C: SPIFFE/SPIRE (mTLS with X.509-SVID)
Preferred for zero-trust environments. Two sub-options based on SPIFFE spec:
C1: X.509-SVID with mTLS (recommended)
- Satellite obtains X.509-SVID from local SPIRE agent via Workload API
- Satellite establishes mTLS connection to GC using X.509 certificate
- GC validates certificate against SPIFFE trust bundle
- SPIFFE ID extracted from certificate identifies the satellite
- No additional header needed - identity proven via TLS handshake
C2: JWT-SVID (when mTLS not possible)
- Used when L7 proxy/load balancer sits between satellite and GC
- Satellite obtains JWT-SVID from SPIRE agent via Workload API
- JWT passed in
Authorization: Bearer <jwt-svid> header
- GC validates JWT signature against SPIFFE trust bundle
- SPIFFE ID extracted from JWT
sub claim
- Note: JWT-SVIDs are susceptible to replay attacks, use short TTLs
SPIFFE ID format: spiffe://trust-domain/satellite/<satellite-name>
Value
- Prevents satellite impersonation
- Ensures heartbeat data integrity
- Foundation for satellite revocation
- Required for security compliance
- SPIFFE option enables zero-trust architecture
Changes to be Made
Files to Modify
Satellite:
internal/state/reporting_process.go (add auth header)
Ground Control:
ground-control/internal/server/middleware.go (satellite auth middleware)
ground-control/internal/server/routes.go (apply middleware)
ground-control/internal/server/satellite_handlers.go
SPIFFE Resources
Context
Satellites send heartbeat/status reports to Ground Control via
POST /satellites/sync. This endpoint should validate that requests come from legitimate registered satellites.Current State
Satellite side (
internal/state/reporting_process.go:120-154):/satellites/syncwith JSON bodyContent-Type: application/jsonheaderGC side (
ground-control/internal/server/satellite_handlers.go:358):namefield from request bodySecurity Issue: Anyone who knows a satellite name can impersonate it and send fake status reports. The route is public (not under protected subrouter).
Expected Behavior
Option A: Robot Account Credentials (ZTR)
Option C: SPIFFE/SPIRE (mTLS with X.509-SVID)
Preferred for zero-trust environments. Two sub-options based on SPIFFE spec:
C1: X.509-SVID with mTLS (recommended)
C2: JWT-SVID (when mTLS not possible)
Authorization: Bearer <jwt-svid>headersubclaimSPIFFE ID format:
spiffe://trust-domain/satellite/<satellite-name>Value
Changes to be Made
/satellites/syncFiles to Modify
Satellite:
internal/state/reporting_process.go(add auth header)Ground Control:
ground-control/internal/server/middleware.go(satellite auth middleware)ground-control/internal/server/routes.go(apply middleware)ground-control/internal/server/satellite_handlers.goSPIFFE Resources