IoT
Categories:
4 minute read
Introduction
AWS IoT provides cloud services to manage IoT fleet and integrate them with other AWS services
LocalStack Pro supports IoT Core, IoT Data, IoT Analytics and related APIs as well as an in-built MQTT broker. Common operations for creating and updating things, groups, policies, certificates and other entities are implemented with full CloudFormation support. The supported APIs are available on our API coverage page.
Getting Started
This guide is for users that are new to IoT and assumes a basic knowledge of the AWS CLI and LocalStack awslocal
wrapper.
Start LocalStack using your preferred method.
LocalStack ships an Message Queuing Telemetry Transport (MQTT) broker powered by Mosquitto which supports both pure MQTT and MQTT-over-WSS (WebSockets Secure) protocols.
To retrieve the MQTT endpoint, use the DescribeEndpoint
operation.
$ awslocal iot describe-endpoint
{
"endpointAddress": "000000000000.iot.eu-central-1.localhost.localstack.cloud:4510"
}
Tip
LocalStack lazy-loads services by default. The MQTT broker may not be automatically available on a fresh launch of LocalStack. You should make aDescribeEndpoint
call to ensure the broker is running and identify the port.This endpoint can then be used with any MQTT client to publish and subscribe to topics. In this example, we will use the Hive MQTT CLI.
Run the following command to subscribe to an MQTT topic.
$ mqtt subscribe \
--host 000000000000.iot.eu-central-1.localhost.localstack.cloud \
--port 4510 \
--topic climate
In another terminal, publish a message to this topic.
$ mqtt publish \
--host 000000000000.iot.eu-central-1.localhost.localstack.cloud \
--port 4510 \
--topic climate \
-m "temperature=30°C;humidity=60%"
This message will be pushed to all subscribers of this topic, including the one in the first terminal.
Authentication
LocalStack IoT maintains its own root certificate authority which is regenerated at every run. The root CA certificate can be retrieved from http://localhost.localstack.cloud:4566/_aws/iot/LocalStackIoTRootCA.pem.
Note
AWS provides its root CA certificate at https://www.amazontrust.com/repository/AmazonRootCA1.pem. For more information, see this.When connecting to the endpoints, you will need to provide this root CA certificate for authentication. This is illustrated below with Python AWS IoT SDK,
import awscrt
import boto3
from awsiot import mqtt_connection_builder
region = 'eu-central-1'
iot_client = boto3.client('iot', region=region)
endpoint = aws_client.iot.describe_endpoint()["endpointAddress"]
endpoint, port = endpoint.split(':')
event_loop_group = io.EventLoopGroup(1)
host_resolver = io.DefaultHostResolver(event_loop_group)
client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)
credentials_provider = awscrt.auth.AwsCredentialsProvider.new_static(
access_key_id='...',
secret_access_key='...',
)
client_id = 'example-client'
# Path to root CA certificate downloaded from `/_aws/iot/LocalStackIoTRootCA.pem`
ca_filepath = '...'
mqtt_over_wss = mqtt_connection_builder.websockets_with_default_aws_signing(
region=region,
credentials_provider=credentials_provider,
client_bootstrap=client_bootstrap,
client_id=client_id,
endpoint=endpoint,
port=port,
ca_filepath=ca_filepath,
)
mqtt_over_wss.connect().result()
mqtt_over_wss.subscribe(...)
If you are using pure MQTT, you also need to set the client-side X509 certificates and Application Layer Protocol Negotiation (ALPN) for a successful mutual TLS (mTLS) authentication. This is not required for MQTT-over-WSS since it does not use mTLS.
AWS IoT SDKs automatically set the ALPN when the endpoint port is 443. However, because LocalStack does not use this port, this must be done manually. For details on how ALPN works with AWS, see this page.
The client certificate and key can be retrieved using CreateKeysAndCertificate
operation.
The certificate is signed by the LocalStack root CA.
result = iot_client.create_keys_and_certificate(setAsActive=True)
# Path to file with saved content `result["certificatePem"]`
cert_file = '...'
# Path to file with saved content `result["keyPair"]["PrivateKey"]`
priv_key_file = '...'
tls_ctx_options = awscrt.io.TlsContextOptions.create_client_with_mtls_from_path(
cert_file, priv_key_file
)
tls_ctx_options.alpn_list = ["x-amzn-mqtt-ca"]
mqtt = mqtt_connection_builder._builder(
tls_ctx_options,
cert_filepath=cert_file,
pri_key_filepath=priv_key_file,
client_bootstrap=client_bootstrap,
client_id=client_id,
endpoint=endpoint,
port=port,
ca_filepath=ca_filepath,
)
mqtt.connect().result()
mqtt.subscribe(...)
Lifecycle Events
LocalStack publishes the lifecycle events to the standard endpoints.
$aws/events/presence/connected/clientId
: when a client connects$aws/events/presence/disconnected/clientId
: when a client disconnects$aws/events/subscriptions/subscribed/clientId
: when a client subscribes to a topic$aws/events/subscriptions/unsubscribed/clientId
: when a client unsubscribes from a topic
Currently the principalIdentifier
and sessionIdentifier
fields in event payload contain dummy values.
Registry Events
LocalStack can publish the registry events, if you enable it.
$ awslocal iot update-event-configurations \
--event-configurations '{"THING":{"Enabled": true}}'
You can then subscribe or use topic rules on the follow topics:
$aws/events/thing/<thingName>/created
: when a new thing is created$aws/events/thing/<thingName>/updated
: when a thing is updated$aws/events/thing/<thingName>/deleted
: when a thing is deleted
Topic Rules
It is possible to use actions with SQL queries for IoT Topic Rules.
For example, you can use the CreateTopicRule
operation to define a topic rule with a SQL query SELECT * FROM 'my/topic' where attr=123
which will execute a trigger whenever a message with attribute attr=123
is received on the MQTT topic my/topic
.
Supported triggers include Kinesis, Lambda, SQS, Firehose and DynamoDB v2.
Current Limitations
LocalStack MQTT broker does not support multi-account/multi-region namespacing.
Internally, the MQTT messages are not routed to the appropriate account ID/region even though the endpoint URL may suggest otherwise.
All messages will be routed to the 000000000000
account and the us-east-1
region.
This prevents features such as topic rules from working properly when not using the this account ID or region.