ZeroStream — offboard vehicle-data streaming

ZeroStream

Offboard vehicle-data streaming

Switch user

What it is

ZeroStream carries live vehicle data from a device on a rig to the Customer Zero back-office. The device publishes MQTT 5 over TLS to AWS IoT Core, and IoT Core turns the values into CloudWatch metrics per device and signal.

A device's identity is a certificate from ZeroPKI (Offboard Issuing CA). IoT Core trusts only that CA and registers a device the first time it connects, so no one adds devices to IoT Core by hand.

Endpoint and trust

Endpoint
…
Port
8883 (MQTT 5 over TLS 1.2+)
Client cert
ZeroPKI Offboard, service zero_stream_device. Present the full chain (leaf plus intermediates).
Server trust
Amazon Root CA 1 (AmazonRootCA1.pem)
SNI
Required. Connect by hostname; Paho sends SNI by itself.

Device names

A device is called device- followed by six lowercase hex characters, for example device-0a0001. The same name is the cert CN, the IoT thing name, the MQTT client id, the topic segment and the Device dimension. ZeroPKI signs no other form for this service, and IoT Core accepts no other client id for the cert.

Later, the physical id of the hardware (a UUID, or chassis number plus serial number) is recorded against the device name. The name itself never changes.

Topics

TopicDirectionCarries
…device → cloudone signal value, {"value": <number>, "ts": "<ISO 8601>"}
…device → cloudlifecycle: connected, graceful shutdown, last will
…cloud → devicea request, e.g. ping
…device → cloudthe answer to that request

A device can publish and receive only under its own name. Signals that become metrics: …. Anything else published under tele/ is dropped, and event is never a signal.

Metrics

NamespaceMetricDimensions
…ValueDevice, Signal
…ConnectionState (1 connected, 0 disconnected)Device

CloudWatch buckets at one minute. Only cert-authenticated clients count as devices, so the console MQTT client never shows up.

Enroll a device

The key is made on the device and never leaves it; only the CSR travels.

On the rig in ZeroTwin (anyone with write access)

  1. Open the rig in ZeroTwin → Rigs and, under Streaming device, add the device with its physical id. ZeroTwin shows the device name it minted, e.g. device-0cf12e.
  2. On the device, make a P-384 key and a CSR for that name:
    NAME=device-0cf12e
    openssl ecparam -name secp384r1 -genkey -noout -out $NAME.key.pem
    openssl req -new -key $NAME.key.pem -subj "/CN=$NAME" -out $NAME.csr
    openssl req -in $NAME.csr -outform DER | shasum -a 256   # compare with the rig page
  3. Paste or upload the CSR under Allow the device key, check the fingerprint, and allow it. Download $NAME.fullchain.pem and copy it to the device, next to its key.

By an operator (AWS SSO, cz-dev DevAccess)

  1. On the device, pick a name and make a P-384 key and CSR:
    NAME=device-$(openssl rand -hex 3)
    openssl ecparam -name secp384r1 -genkey -noout -out $NAME.key.pem
    openssl req -new -key $NAME.key.pem -subj "/CN=$NAME" -out $NAME.csr
  2. Copy $NAME.csr to an operator, who submits it to ZeroPKI from the zero-backoffice repo:
    sesh CustomerZeroDev cz-developer DevAccess
    python3 iac-internal/zero-pki-aws/scripts/request_cert.py zero_stream_device --csr $NAME.csr
    This writes coretura-pki-certs/zero_stream_device/$NAME.fullchain.pem and verifies the chain.
  3. Copy $NAME.fullchain.pem back to the device, next to its key.

Connect

Connect to the endpoint with the full chain as client cert, the key, Amazon Root CA 1 as server trust, and the device name as client id. The very first connection is dropped while IoT Core registers the device; reconnect and it streams. The reference publisher does both:

curl -sO https://www.amazontrust.com/repository/AmazonRootCA1.pem
shasum -a 256 AmazonRootCA1.pem
# expect 2c43952ee9e000ff2acc4e2ed0897c0a72ad5fa72c3d934e81741cbd54f05bd1
pip install "paho-mqtt>=2"
python3 iac-internal/zero-stream-aws/scripts/publish.py \
  --endpoint … \
  --cert $NAME.fullchain.pem --key $NAME.key.pem

On a real device, the Coretura Linux connectivity image carries Paho C/C++ and a trust store with Amazon Root CA 1. Point it at the same endpoint, cert and topics.

Rotate the cert

  1. Enroll again with the same name: new key, new CSR, new fullchain.
  2. Switch the device to the new cert and key. On first use IoT Core registers the new cert on the existing device.
  3. Deactivate the old cert:
    aws iot list-thing-principals --thing-name $NAME
    aws iot update-certificate --certificate-id <old-id> --new-status INACTIVE

Revoke

On the rig in ZeroTwin, Remove device revokes all its certs and deletes it; adding the hardware again gives it a new name. An operator can instead set one cert to REVOKED (permanent) or INACTIVE (can be undone). The device is refused on its next connect, and a reconnect never switches the cert back on.

aws iot list-thing-principals --thing-name $NAME
aws iot update-certificate --certificate-id <id> --new-status REVOKED

ZeroPKI does not publish a CRL yet, so the cert status in IoT Core is the only way to block a device.

Watch the stream

With an AWS SSO session in cz-dev, open the IoT Core MQTT test client and subscribe to …. No cert is needed.

Read the data

In CloudWatch (cz-dev, eu-north-1), graph Value from … per Device and Signal, and ConnectionState from … per Device.

An external Grafana (e.g. in the Coretura account) reads these through CloudWatch cross-account observability (OAM), which shares only the chosen namespaces. A read role cannot be limited to a namespace. OAM is regional: the sink lives in eu-north-1 of the monitoring account, and Grafana queries that region.