Skip to content

Commit

Permalink
Revamp IoT docs (#813)
Browse files Browse the repository at this point in the history
  • Loading branch information
viren-nadkarni authored Sep 21, 2023
1 parent 7b7b20a commit 0876c3e
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 13 deletions.
2 changes: 1 addition & 1 deletion content/en/user-guide/aws/elastic-compute-cloud/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Once the instance is up and running, we can use the `ssh` command to set up an S
{{< command >}}
$ ssh -p 12862 -i key.pem [email protected]
{{< /command >}}
{{< alert title="Hint" color="info">}}
{{< alert title="Hint" color="success">}}
If the `ssh` command throws an error like "Identity file not accessible" or "bad permissions", then please make sure that the key file has a restrictive `0400` permission as illustrated [here](#create-a-key-pair).
{{< /alert >}}
## Docker backend
Expand Down
146 changes: 134 additions & 12 deletions content/en/user-guide/aws/iot/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@ aliases:
- /aws/iot/
---

LocalStack Pro supports IoT Core, IoT Data, IoT Analytics and related APIs.
## 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](https://docs.localstack.cloud/references/coverage/coverage_iot/).

## Getting Started

## MQTT Broker
This guide is for users that are new to IoT and assumes a basic knowledge of the AWS CLI and LocalStack [`awslocal`](https://github.com/localstack/awscli-local) wrapper.

LocalStack ships with a built-in MQTT broker.
Start LocalStack using your preferred method.

LocalStack ships an Message Queuing Telemetry Transport (MQTT) broker powered by [Mosquitto](https://mosquitto.org/) which supports both pure MQTT and MQTT-over-WSS (WebSockets Secure) protocols.
To retrieve the MQTT endpoint, use the [`DescribeEndpoint`](https://docs.aws.amazon.com/iot/latest/apireference/API_DescribeEndpoint.html) operation.

{{< command >}}
Expand All @@ -23,17 +32,129 @@ $ awslocal iot describe-endpoint
}
{{< / command >}}

This endpoint can then be used with any MQTT client to publish and subscribe to topics.

{{< alert title="Hint" color="success" >}}
LocalStack lazy-loads services by default.
The MQTT broker may not be automatically available on a fresh launch of LocalStack.
You should make a `DescribeEndpoint` call to ensure the broker is running.
You should make a `DescribeEndpoint` call to ensure the broker is running and identify the port.
{{< /alert >}}

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](https://hivemq.github.io/mqtt-cli/docs/installation/).

Run the following command to subscribe to an MQTT topic.

{{< command >}}
$ mqtt subscribe \
--host localhost.localstack.cloud \
--port 4510 \
--topic climate
{{< /command >}}

In another terminal, publish a message to this topic.

{{< command >}}
$ mqtt publish \
--host localhost.localstack.cloud \
--port 4511 \
--topic climate \
-m "temperature=30°C;humidity=60%"
{{< /command >}}

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://local.localstack.cloud:4566/_aws/iot/LocalStackIoTRootCA.pem>.

{{< alert title="Note">}}
AWS provides its root CA certificate at <https://www.amazontrust.com/repository/AmazonRootCA1.pem>.
For more information, see [this](https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs).
{{< /alert >}}

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](https://docs.aws.amazon.com/iot/latest/developerguide/iot-sdks.html),

```py
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_default_chain(
client_bootstrap=client_bootstrap
)

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](https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html).

The client certificate and key can be retrieved using `CreateKeysAndCertificate` operation.
The certificate is signed by the LocalStack root CA.

```py
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 also publishes the [lifecycle events](https://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html) to the standard endpoints.
LocalStack publishes the [lifecycle events](https://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html) to the standard endpoints.

- `$aws/events/presence/connected/clientId`: when a client connects
- `$aws/events/presence/disconnected/clientId`: when a client disconnects
Expand All @@ -42,19 +163,20 @@ LocalStack also publishes the [lifecycle events](https://docs.aws.amazon.com/iot

Currently the `principalIdentifier` and `sessionIdentifier` fields in event payload contain dummy values.

## Registry Events for Things
## Registry Events

LocalStack can publish the [registry events](https://docs.aws.amazon.com/iot/latest/developerguide/registry-events.html), if [you enable it](https://docs.aws.amazon.com/iot/latest/developerguide/iot-events.html#iot-events-enable).

{{< command >}}
$ awslocal iot update-event-configurations --event-configurations "{\"THING\":{\"Enabled\": true}}"
$ awslocal iot update-event-configurations \
--event-configurations '{"THING":{"Enabled": true}}'
{{< / command >}}

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
- `$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

Expand Down

0 comments on commit 0876c3e

Please sign in to comment.