CPS / IoT device attestation
When you'd use this
The dashboard's CPS Device Fleet panel surfaces device-level attestation status alongside a risk score. This runbook explains what the columns mean, when to investigate a device, and how to escalate.
Columns
- Device ID, the deterministic identifier the device presented at enrollment.
- Type, PLC, RTU, HMI, IP-Cam, Gateway, etc. Determines which policy bundle applies.
- Attestation,
verified: the device's last attestation report matched the expected hash, certificate chain, and firmware version.pending: a report has been issued but not yet reviewed (the attestation worker is behind, or the device is in burn-in).revoked: the device's cert was revoked; it cannot re-attest until re-enrolled.
- Risk, a 0–100% score combining firmware version drift, observed telemetry anomalies, and known IOC hits. Bar colour is red above 70%, yellow above 30%, green below.
- Location, the physical site reading from the site controller.
What to investigate
- Risk above 70%, review the device detail. The detail page shows the trail of telemetry that drove the score and any related cases. Decide whether to dispatch the CPS Security agent, isolate the device on the OT segment, or escalate to facilities.
- Pending attestation, usually transient. If a device
sits in pending for more than 24 hours, the attestation
worker is behind or the device is silent. Check the
observability page for
attestation_pending_total. - Revoked attestation, the device is locked out of the OT bus. Re-enrollment requires a facilities sign-off and a fresh OTT (one-time token).
Escalation
- Network anomaly on an OT device, pair with the Network Attack triage runbook. OT segments produce false positives easily; the correlator's confidence number is your filter.
- Firmware drift, open a case linked to the device and attach the firmware inventory snapshot. The firmware workflow is owned by the platform team; your job is to observe and document, not to update firmware from the operator console.
What goes wrong
- The risk score does not match what you see in the field, the policy bundle that drives the score may be stale; check the page footer for the bundle version. The bundle refresh is owned by the platform team.
- A device disappears from the list, either the device went offline (lost telemetry) or the site controller for that location is down. The Sites page shows controller liveness.
- The CPS Security agent dispatch times out, the underlying
MCP server may be down. Check the observability dashboard
for the
cpsMCP server status.
Key provisioning
CPS devices use the DICE (Device Identifier Composition Engine) Layering Architecture for cryptographic identity. The key hierarchy starts with a device-unique hardware secret and derives upward.
Step 1: Generate device-unique seed
The device reads its UDS (Unique Device Secret) from a one-time- programmable fuse or secure element. This value is never readable outside the secure boot path.
UDS = read_fuse(FUSE_UDS)
Step 2: Derive the CDI
The Compound Device Identifier is computed by hashing the UDS with the hash of the first mutable code (Layer 0 firmware):
CDI = HMAC-SHA256(UDS, SHA256(Layer0_Firmware))
If firmware changes, the CDI changes. This is intentional: a compromised firmware image produces a different CDI that cannot impersonate the authorised device.
Step 3: Request an enrollment token
The device sends its CDI (as a public commitment, never the raw UDS) to the OTT (One-Time Token) service:
POST /api/v1/cps/ott/request
{
"device_id": "PLC-BAY7-03",
"cdi_commitment": "sha256:ab12...ef34",
"device_type": "PLC",
"firmware_version": "v2.4.1"
}
The OTT service returns a single-use enrollment token valid for 60 seconds:
{
"ott": "eyJhbGciOi...",
"expires_at": "2026-06-14T12:01:00Z"
}
Step 4: Enroll x.509 certificate via EST
The device uses the OTT to authenticate against the EST (Enrollment over Secure Transport) endpoint:
POST /api/v1/cps/est/enroll
Authorization: Bearer {ott}
Content-Type: application/pkcs10
-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----
AuroraSOC signs the CSR and returns the device certificate. The device stores it in its secure element alongside the private key.
Step 5: Confirm enrollment
GET /api/v1/cps/devices/PLC-BAY7-03
The device should now appear in the CPS Device Fleet dashboard with
attestation status pending. Proceed to operator approval.
Device enrollment workflow
-
Device boots with DICE-validated firmware. The secure boot path computes the CDI from UDS + Layer 0 hash. If the hash mismatches the golden image, the device halts and surfaces a tamper event.
-
Device connects to the AuroraSOC MQTT broker on the OT segment (port 8883 with mutual TLS). It presents its CDI commitment in the enrollment topic:
Topic: cps/enroll/PLC-BAY7-03Payload: {"cdi_commitment": "sha256:ab12...", "model": "S7-1200", "fw": "v2.4.1"} -
The OTT (One-Time Token) service validates the commitment against the site controller's device inventory. If the device is expected (pre-registered by facilities), an OTT is issued.
-
The device calls the EST endpoint with the OTT to obtain its x.509 certificate. The certificate is signed by the AuroraSOC internal CA with the device's CDI commitment as a SAN extension.
-
The device appears in the CPS Device Fleet dashboard with status
pending. An operator reviews the device entry and clicks Approve. This moves the device toverifiedand enables periodic attestation challenges. -
If the operator clicks Reject, the certificate is revoked and the device is removed from the fleet view. A case is auto-created with the rejection reason for audit trail.
Challenge-response configuration
Periodic attestation proves the device still runs the authorised firmware and holds the original key. The parameters are tuned per device criticality.
Challenge parameters
| Parameter | Critical devices | Standard devices |
|---|---|---|
| Nonce size | 32 bytes | 32 bytes |
| Challenge interval | 5 minutes | 30 minutes |
| Allowed clock skew | 2 seconds | 2 seconds |
| Attestation timeout | 10 seconds | 10 seconds |
| Failure threshold | 3 consecutive failures | 3 consecutive failures |
Configure from the dashboard under Settings > CPS > Attestation, or via the API:
PATCH /api/v1/settings/runtime
{
"cps_attestation": {
"nonce_size": 32,
"challenge_interval_critical_s": 300,
"challenge_interval_standard_s": 1800,
"allowed_clock_skew_s": 2,
"attestation_timeout_s": 10,
"failure_threshold": 3
}
}
Challenge message
AuroraSOC publishes a challenge to the device's MQTT topic:
{
"type": "attestation_challenge",
"device_id": "PLC-BAY7-03",
"nonce": "8f3a91bc02d7e4c5a1b6f8093d2e7c1a",
"timestamp": "2026-06-14T12:00:00Z",
"challenge_id": "ch-9a2b"
}
Expected response
The device must respond within the timeout with a signed response on
the topic cps/attest/response:
{
"type": "attestation_response",
"challenge_id": "ch-9a2b",
"device_id": "PLC-BAY7-03",
"nonce": "8f3a91bc02d7e4c5a1b6f8093d2e7c1a",
"firmware_hash": "sha256:3d4e...",
"cert_chain": ["-----BEGIN CERTIFICATE-----..."],
"signature": "MEUCIQD...",
"timestamp": "2026-06-14T12:00:03Z"
}
The nonce must match exactly. The firmware hash must match the golden value registered during enrollment. The certificate chain must validate against the AuroraSOC internal CA. The signature must verify with the device's public key.
Verification and result interpretation
Statuses
| Status | Colour | Meaning | Action |
|---|---|---|---|
verified | Green | Firmware hash, certificate chain, and nonce all pass | No action. Device is trusted. |
pending | Yellow | Challenge sent but response not yet reviewed, or device is in burn-in | Wait for next cycle. Escalate if > 24 hours. |
failed | Red | Hash mismatch, nonce mismatch, or certificate chain validation error | Investigate immediately. Open case. |
revoked | Black | Device certificate has been revoked | Device locked out. Re-enrollment required. |