Skip to main content

Control-Plane Integrations

The backend is the control plane for sensors. It never touches the alert data path (that is Suricata → sensor → data collector → Kafka). Instead it is responsible for trust and commands: issuing claim codes and certificates, provisioning NATS credentials, sending start/stop commands, and tracking sensor status.

This page maps the backend services that implement those responsibilities. For the end-to-end walkthrough, see the Control Plane scenario.


Responsibilities at a glance


1. Claim codes and enrollment

A sensor is onboarded with a one-time claim code, not an SSH/Ansible push. The relevant controllers:

ControllerRole
API/Controllers/ClaimCodes/ClaimCodesController.csOperator-facing claim-code management.
API/Controllers/ClaimCodes/SensorClaimController.csSensor-facing claim redeem (POST /api/sensors/claim/redeem).
API/Controllers/Sensors/SensorsController.csSensor registration, enrollment (CSR → cert), heartbeat, cert renew/revoke.

The enrollment exchange (POST /api/sensors/{id}/agent/enroll) takes the sensor's CSR and returns a signed mTLS client certificate plus a sensor token. See Sensor → Enrollment & PKI for the client side.


2. gRPC services (mTLS)

Two gRPC services are mapped in Extensions/WebApplicationExtensions.cs:

app.MapGrpcService<SensorHealthcheckService>();
app.MapGrpcService<SensorEventStreamService>();
  • SensorHealthcheckService (Protos/sensor_healthcheck.proto) — sensors report health.
  • SensorEventStreamService (Protos/sensor_event.proto) — the target mTLS ingestion path for alert events. Currently it authenticates the client certificate and enforces liveness (it logs events and checks the client-cert serial against the active sensor list) rather than persisting to Kafka. The operational data path today still flows through the Data Collector; see the Data Plane scenario for how the two relate.

Both are guarded by SensorMtlsInterceptor (Infrastructure/Grpc/SensorMtlsInterceptor.cs), registered via AddGrpc(options => options.Interceptors.Add(typeof(SensorMtlsInterceptor))) in Extensions/ServiceCollectionExtensions.cs.


3. NATS account/user provisioning

The backend does not sign any NATS JWTs — it delegates to the NATS Provisioner.

ServiceFileRole
NatsProvisionerClientInfrastructure/Services/NatsProvisionerClient.csHTTP client for POST /accounts, POST /users, POST /revoke. Sends the shared secret via SharedSecretHeaderName and routes calls through the resilient HTTP service (circuit breaker key nats-provisioner).
NatsTenantProvisioningWorkerInfrastructure/Services/NatsTenantProvisioningWorker.csBackgroundService that reconciles tenants whose NatsAccountPubKey is null or status pending, calls CreateAccountAsync, then MarkNatsAccountProvisioned. Runs every IntervalSeconds (min 5s).

Both are gated by NatsProvisionerOptions.Enabled; when disabled they throw/return rather than calling out.


4. NATS control messaging

Once credentials exist, the backend talks to sensors over NATS:

ServiceFileSubjectRole
NatsControlPublisherInfrastructure/Services/NatsControlPublisher.csrxc.<tenant>.<sensor>.cmd (JetStream)Publishes SensorControlCommand (start/stop) onto the command stream. Subject built by CommandSubject(tenantId, sensorId). Requires NatsMessagingOptions.Enabled.
VirtualSensorStatusConsumerInfrastructure/Services/VirtualSensorStatusConsumer.csrxc.*.*.status (core NATS)Subscribes to all sensor status subjects, matches each message to a virtual sensor, and applies status transitions (Apply).

Commands go out over JetStream (durable, work-queue) so a sensor that is briefly offline still receives them. Status comes back over core NATS as fire-and-forget telemetry.


Configuration summary

Option groupDrives
NatsProvisionerOptions (Enabled, BaseUrl, SharedSecret, SharedSecretHeaderName, IntervalSeconds)Provisioner HTTP client + reconcile worker.
NatsMessagingOptions (Enabled, connection/creds)Control publisher + status consumer.

See Configuration Reference for the concrete keys, and NATS Provisioner for the service on the other side of the shared secret.