Skip to content

Security Trust Model

Telovix separates four independent trust domains: control-plane trust between sensors and the Console, policy trust for runtime behavior, operator access trust for the Console UI and API, and commercial trust for entitlements. Each domain has distinct mechanisms and failure modes. Understanding the boundaries prevents misdiagnosis when something goes wrong and prevents incorrect assumptions about what a compromised component can affect.


The four trust domains

DomainWhat it governsMechanism
Control-plane trustSensor identity and communication with ConsoleMutual TLS with per-sensor client certificates
Policy trustWhether a policy pack may execute on a sensorEd25519 signature verification per policy file
Operator access trustWho can read and write Console stateSession authentication, RBAC, optional SSO and MFA
Commercial trustWhether a deployment is entitled to runOffline Ed25519-signed license bundles

These four domains are intentionally independent. A compromised enrollment token does not affect policy trust. A license expiry does not revoke sensor certificates. A rogue operator session cannot bypass policy signature verification on the sensor.


Control-plane trust: sensor to Console

Enrollment

During enrollment, the sensor generates a local RSA key pair using rcgen and creates a Certificate Signing Request with CN=<node_name>, O=Telovix Sensor. It presents an enrollment token alongside this CSR to the Console enrollment endpoint. The Console verifies the token and signs the CSR, issuing a client certificate with a 720-hour (30-day) TTL by default.

The enrollment token is a bootstrap secret only. It is consumed at enrollment time. After enrollment, the durable sensor identity is the client certificate, not the token.

The Telovix Console returns:

  • control_plane_certificate_pem: the signed client certificate
  • control_plane_ca_certificate_pem: the Console's CA certificate
  • policy_signing_public_key_pem: the Ed25519 public key for policy verification
  • certificate_expires_at: expiry timestamp in RFC3339 format
  • certificate_reference: internal reference ID

The sensor atomically writes all of these to the state directory (/var/lib/telovix-sensor by default). The sensor-state.json file records trust_state="trusted" and renewal_status="ok".

All subsequent communication

Every heartbeat, WebSocket connection, and policy download uses outbound mTLS. The sensor presents its client certificate on every request. The Console validates the certificate against its CA on every request. There is no API key or session token fallback for sensor communication.

Renew certificates

Renewal is triggered by two conditions:

TriggerCondition
Proactive renewalCertificate expiry is less than 72 hours away
Manual renewalOperator increments the manual_renewal_generation counter via Console

The renewal process generates a new CSR and submits it to the Console renewal endpoint. The Console issues a new certificate. The sensor writes the new key first, then the certificate, so that a crash mid-write triggers re-enrollment rather than leaving a corrupt state.

The default certificate TTL is 720 hours (30 days). The renewal-due threshold defaults to 86400 seconds (1 day). Both are configurable in Console Settings.

Read trust states

StateMeaning
trustedCertificate is valid; mTLS is working
renewal_recommendedCert is approaching expiry but still within tolerance
renewal_dueCert expiry is within the renewal threshold; renewal should happen immediately
trust_revokedConsole revoked this sensor; mTLS will stop working

When trust state is trust_revoked, the sensor stops forwarding events and the Console rejects all requests from that sensor. Trust alerts are visible on the Fleet > Trust Alerts page in the Console and on each sensor's Trust tab.

Understand trust state and enforcement

A sensor whose trust health is not healthy is blocked from transitioning to enforcement mode. The enforcement readiness check requires the sensor to have healthy trust before allowing the enforce_ready or enforced state.


Policy trust: runtime behavior

Verify policy delivery

Policy packs are delivered from the Console to the sensor as YAML files. Each policy file may be accompanied by a .sig sidecar file containing an Ed25519 signature, base64-encoded.

The Console holds an Ed25519 signing key at the path configured during setup (default: policy-signing.ed25519). The sensor receives the corresponding public key during enrollment and stores it at policy-signing.pub.

When loading a policy file, the sensor follows this logic:

  1. If a .sig sidecar exists: load the public key from policy-signing.pub, verify the signature against telovix-policy-v1:{policy_name}\n{yaml_content}, and reject the policy if verification fails.
  2. If no .sig sidecar exists but a signing key is present: log a warning and proceed (backward compatibility with pre-signing deployments).
  3. If no .sig sidecar and no signing key: skip verification.

The signature format telovix-policy-v1:{name}\n{content} binds the policy name to its content. A policy file cannot be renamed and applied under a different name without invalidating the signature.

This means a policy injected by an attacker who can write to the sensor's state directory but does not have the Console's Ed25519 private key will be rejected at load time.


Operator access trust

Authentication

Console users authenticate with email and password. Sessions are issued as secure, HTTP-only cookies. TOTP-based MFA is available and can be required per user. The Console supports SAML 2.0 and OpenID Connect (OIDC) for SSO. SSO configuration is stored in the Console database and managed from Settings > SSO in the Console UI.

API keys are scoped alternatives to session authentication for programmatic access. API keys are created by authenticated users and can be revoked individually.

Role-based access control

RoleLevelWhat it can do
viewer1Read-only access to sensors, events, and reports
analyst2All viewer permissions plus investigation and alert management
sensor_owner3All analyst permissions plus sensor management for owned sensors
operator3All analyst permissions plus policy management, enforcement changes, and exercise creation
admin4Full access including user management, settings, and license import

Role levels are enforced server-side on every request. The require_operator and require_admin middleware functions gate the relevant API routes. Role elevation requires an admin user.


Commercial trust: license validation

License structure

The Portal issues signed license bundles. Each bundle is a JSON envelope with the structure:

json
{
  "schema_version": 1,
  "signature_algorithm": "ED25519",
  "payload": {
    "customer_id": "...",
    "workspace_id": "...",
    "license_id": "lic-...",
    "plan": "growth",
    "max_protected_nodes": 250,
    "valid_from": "...",
    "valid_until": "...",
    "grace_until": "...",
    "issued_at": "..."
  },
  "signature": "<base64-encoded-ed25519-signature>"
}

The grace_until field extends the license beyond valid_until for a configurable grace period (default: 30 days). During the grace period, the deployment remains operational but the Console displays an expiry warning.

Signing

The Portal's license signing service exposes a single internal endpoint at POST /internal/v1/sign-license. This service is not reachable from the public internet. It loads the Ed25519 signing key from the path configured at deployment time, serializes the payload to canonical JSON, signs it, and returns the envelope. Communication between the Portal and the signing service is authenticated with a shared secret compared using constant-time comparison.

Console validation

The Console validates license bundles offline. It does not contact the Portal or any external service at validation time. The operator imports the signed bundle via the setup wizard or from Settings > License in the Console. The Console verifies the Ed25519 signature against its embedded public key and checks valid_until and grace_until against the current time.

This offline model means the Console continues operating in air-gapped or network-isolated environments as long as the imported license has not expired. The Console does not depend on Stripe connectivity, Portal availability, or any cloud service for runtime entitlement decisions.

Understand why commercial trust is separate

The Stripe payment flow, Portal workspace state, and billing webhook processing all feed the Portal. The Portal issues a signed license. The Console trusts only the signature on that license bundle, not any runtime state from Stripe or the Portal. This means:

  • Stripe refunds, disputes, or service outages do not affect the Console's license state
  • A compromised Portal cannot issue a license with capabilities beyond what the Ed25519 signing key authorizes
  • A stolen or replayed license bundle is only as dangerous as the private key that signed it

Trust boundary violations and what they mean

ViolationWhat is affectedWhat is not affected
Stolen enrollment tokenCan enroll a rogue sensor during the token's valid windowDoes not compromise existing sensors; revoke the token immediately
Stolen sensor client certificateCan send forged heartbeats from that sensor identityDoes not affect other sensors; revoke via Console trust management
Compromised policy signing keyCan inject arbitrary policy into sensors that trust this keyDoes not affect sensors with no signing key (they skip verification with a warning); rotate the key and re-enroll
Expired licenseConsole blocks new sensor enrollments above the node limit; grace period provides 30-day bufferDoes not revoke sensor certificates or stop active monitoring on enrolled sensors
Stolen operator sessionAttacker has operator-level Console accessCannot bypass mTLS on existing sensors; cannot forge signed policy without the Ed25519 key

Monitor trust from the Console

Console pageWhat it shows
Fleet (header)Fleet-wide trust health summary with counts by trust state
Fleet > Trust AlertsAll active trust alerts across the fleet
Sensors > [sensor] > Trust tabDetailed trust state, certificate expiry, and renewal status for one sensor
Sensors > [sensor] > Trust tab > Trigger RenewalTriggers manual certificate renewal
Settings > LicenseImport a signed license bundle; view current license status

Operational guidance

Do not share enrollment tokens across hosts. Each token should enroll one sensor. A token reused across multiple hosts means any one of those hosts can abuse the token window to generate additional enrollments. Generate one token per node or cluster from the Deploy Sensor wizard, then immediately verify the sensor appears in Sensors after enrollment.

Keep the policy signing key offline. The Ed25519 policy signing key should not reside on the Console host. Rotate it if the Console host is compromised. After rotation, re-deploy policy packs with new signatures; sensors will accept old signatures until the pack is replaced.

Separate the license signing key from the Portal. The signing service runs as a separate process (backend-license). The key path should point to a key stored on a separate host or HSM. A compromised Portal cannot issue fraudulent licenses unless it can also reach the signing service and knows the shared secret.

Monitor trust alerts. The Fleet > Trust Alerts page in the Console is the earliest signal of certificate expiry or revocation. Configure notifications for trust alert events so sensor certificate expiry does not cause unexpected disconnections.


Further reading

Released under the Telovix Commercial License.