CPI Documentation
Security

Security

Security architecture including mTLS, HMAC signing, JWT authentication, audit logging, and rate limiting.

Security Layers

CPI implements defense-in-depth with 5 security layers for device communication:

LayerMechanismPurpose
1. TransportmTLS (port 8883) or TLS (port 8885)Encrypted communication
2. IdentityX.509 CN (mTLS) or JWT (TOKEN)Device authentication
3. AuthorizationPer-device ACLs (topic-level)Access control
4. IntegrityHMAC-SHA256 signaturesMessage authenticity
5. FreshnessNonce + timestamp validationReplay protection

mTLS Authentication

For high-security deployments, devices connect via mutual TLS on port 8883.

PKI Infrastructure

  • Private CA managed in docker/mosquitto/certs/ca/
  • Scripts in scripts/pki/: init-ca.sh, generate-broker-cert.sh, generate-device-cert.sh
  • PkiModule in the API uses node-forge for cert generation + OpenSSL CLI for CRL

Device Certificate

Each device gets a unique X.509 certificate with:

  • Common Name (CN) = device UUID
  • Signed by the private CA
  • Mosquitto validates CN matches the connecting device ID

Certificate Revocation (CRL)

PkiService.revokeCertificate() generates a CRL via OpenSSL. Mosquitto enforces the CRL via crlfile directive.

Certificate Monitoring

CertMonitorService runs a daily cron job that checks for certificates expiring within 30 days and emits events for notification.

JWT MQTT Authentication (TOKEN)

For partner integrations, devices connect via JWT on port 8885.

  • JWT issued by MqttTokenService during provisioning or token refresh
  • Token passed as MQTT password, device ID as username
  • ACLs embedded in publ (publishable topics) and subs (subscribable topics) claims
  • Separate MQTT_JWT_SECRET from the web API JWT_SECRET
  • Default expiry: 1 hour, maximum: 24 hours

See Partner Integration Guide for full details.

HMAC-SHA256 Signatures

Every message (telemetry, status, commands, ACKs) is signed with a per-device HMAC secret.

Secret Management

  • DeviceSecretsService manages HMAC secrets
  • Secrets encrypted at rest with AES-256-GCM
  • Redis-cached for performance
  • Nonce tracking prevents replay attacks

Enforcement

  • Production: REQUIRE_HMAC_SIGNATURES=true rejects unsigned messages from non-PENDING devices
  • Development: can be relaxed for testing

Secret Rotation

POST /api/v1/devices/{deviceId}/rotate-secret
  • Returns new HMAC secret
  • 1-hour grace period accepts both old and new secrets
  • Use the grace period to update device firmware

Audit Logging

The AuditModule (global) logs all security events to the security_audit_logs table.

Logged Events

Event TypeSeverityExample
AUTH_SUCCESSINFODevice authenticated successfully
AUTH_FAILUREWARNINGInvalid JWT or certificate
HMAC_FAILUREWARNINGMessage signature mismatch
DEVICE_SUSPENDEDHIGHAuto-suspended after rate limit
CERT_REVOKEDHIGHCertificate revoked by admin
SECRET_ROTATEDINFOHMAC secret rotation initiated
DEVICE_DECOMMISSIONEDHIGHDevice permanently revoked

Schema

Each audit log entry contains:

  • Event type and severity level
  • Device ID and/or user ID
  • Timestamp
  • JSONB details field for event-specific data

Rate Limiting

Auth Failure Rate Limiting

ParameterValue
Window5 minutes
Max failures10
ActionAuto-suspend device

When a device exceeds the failure threshold, it is automatically suspended and an audit log entry is created. An admin must manually reactivate the device.

Mosquitto Connection Limits

ParameterValue
Max connections500
Max message size8 KB
Max inflight messages20
Max queued messages1000

Web API Security

Authentication

  • JWT stored in httpOnly cookies (access_token)
  • Extracted from both Cookie header and Authorization: Bearer header
  • Global JwtAuthGuard on all routes (opt-out with @Public())

Authorization

Role-based access control with three levels:

RolePermissions
ADMINFull access: device provisioning, user management, secret rotation
OPERATORDevice monitoring, command sending, alert management
VIEWERRead-only access to dashboards and telemetry

CORS

Configured via ADMIN_URL environment variable. Only the admin dashboard origin is allowed.

On this page