AWS IoT recently launched in beta for everyone so I started poking around with the
AWS IoT Button and the MQTT Broker. At some point I got the idea to connect my existing openHAB Smarthome control system to AWS IoT, to persist the sensor data of my house and/or integrate with the AWS IoT Button. Unfortunately the openHAB MQTT bindings do not support TLS (following the docs) and on the other hand I already had a running Mosquitto MQTT broker. Therefore the idea of bridging messages from one to another broker was born.
This is a short tutorial to setup a bridge between a Mosquitto broker and the AWS IoT broker. There is no need to have openHAB running at all, this is just my use case which I will explain in another blog a bit more. Let's focus on setting up the bridge now:
For any connection to the AWS IoT Broker you need a client, what basically means a set of certificates. The whole process is explained in detail on
AWS IoT Quickstart.
First I'm going to create a new device which is used by the bridge to connect to the broker. You should give it self explaining name:
#aws iot create-thing --thing-name ""
aws iot create-thing --thing-name "mosquittobroker"
{
"thingArn": "arn:aws:iot:us-east-1:xxx:thing/mosquittobroker",
"thingName": "mosquittobroker"
}
Save the
thingArn, you need it later.
You can list all of your devices like this to verify is is created:
aws iot list-things
{
"things": [
{
"attributes": {},
"thingName": "mosquittobroker"
},
...
]
}
Next step is to create the certificates and described on
AWS IoT secure communication
I'm going to list the commands here, but you should really understand what is going on because you have to deal with the certificates later.
# create and activate a certificate:
aws iot create-keys-and-certificate --set-as-active --output text
Save the private and public key as mosquittobroker-private-key.pem and mosquittobroker-public-key.pem
Saving the certificats is easier, because AWS provided ac command for it:
aws iot describe-certificate --certificate-id xxx --output text --query certificateDescription.certificatePem > mosquittobroker-cert.pem
Now your certificate needs a IoT policy (NOT IAM!) which you need to create first.
The policy should have the following setup, save it as policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1445601185404",
"Action": [
"iot:Connect",
"iot:Publish",
"iot:Receive",
"iot:Subscribe"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
To create the policy use the command:
aws iot create-policy --policy-name "Mosquittobroker" --policy-document file://./policy.json
To attach the policy to the certificate execute the command:
# aws iot attach-principal-policy --principal "certificate-arn" --policy-name "PubSubToAnyTopic"
aws iot attach-principal-policy --principal "arn:aws:iot:us-east-1:xxx:cert/xxx" --policy-name "Mosquittobroker"
To attach the certificate to your thing execute the command:
aws iot attach-thing-principal --thing-name "Mosquittobroker" --principal "arn:aws:iot:us-east-1:xxx:cert/xxx"
Verify everything is correct with the following command:
mosquitto_sub --cafile ./iot-root-ca.pem --cert ./mosquittobroker-cert.pem --key ./mosquittobroker-private-key.pem -h ".iot.us-east-1.amazonaws.com" -p 8883 -q 1 -d -t topic/test -i clientid1 --insecure
Depending on your system configuration you might need to use --insecure.
If you would like to find out your AWS IoT endpoint, execute:
aws iot describe-endpoint
The iot-root-ca.pem nees to be downloaded from
https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem, as described in the documentation.
If the connection is successful everything is ready to go ahead with setting up the bride on your Mosquitto broker. You need at least version 1.4 to support TLS and the MQTT v3.1.1.
On Debian you just need to place a configuration file in /etc/mosquitto/conf.d/ named like *.conf. This file should contain the following settings:
# Connection name
connection awsiot
# Host and port of endpoint (your AWS IoT endpoint
address .iot.us-east-1.amazonaws.com:8883
# Default but you should start the bridge automatically
start_type automatic
# Name of the user used to connect to local Mosquitto Broker
local_clientid awsiobridge
# Looks like AWS IoT Broker supports bridges, so we should enable this to for better loop detection
try_private true
# Set the mqtt protocoll to 3.1.1
bridge_protocol_version mqttv311
# AWS IoT Broker will only accept session with cleansession set to true
cleansession true
# AWS IoT Broker will immediately close connections if you try to publish to $SYS, therefore we need to turn off bridge notification (took me a while to find out!)
notifications false
# Topic configuration
# topic pattern [[[ out | in | both ] qos-level] local-prefix remote-prefix]
# topic clients/total in 0 test/mosquitto/org $SYS/broker/
topic yourtopic/ both 0
# Set client ID used on AWS IoT
remote_clientid Mosquittobroker
# Configure certificates like iot-root-ca.pem
bridge_cafile /etc/mosquitto/ca_certificates/iot-root-ca.pem
bridge_certfile /etc/mosquitto/certs/mosquittobroker-cert.pem
bridge_keyfile /etc/mosquitto/certs/mosquittobroker-private-key.pem
# Depending on system configuration, you might need deactivate hostname verification
bridge_insecure false
You need to copy the pem files to the correct folder and make them readable for the Mosquitto user.
You need to configure your own topic patterns, see
. In this example the direction is set to both, messages will flow in both directions. This is very simple and you need to take care of circular message flow, to solve this you should configure local and remote prefix.
Now you need to restart Mosquitto and watch the logfile for the new bridge connection.
It should looks like this output:
mosquitto version 1.4.4 (build date Thu, 17 Sep 2015 16:11:28 +0100) starting
Config loaded from /etc/mosquitto/mosquitto.conf.
Opening ipv4 listen socket on port 1883.
Opening ipv6 listen socket on port 1883.
Connecting bridge awsiot (xxx.iot.us-east-1.amazonaws.com:8883)
...
Not followed by any errors...
If you do have connectivity issues, you should enable CloudWatch Logs as described on AWS IoT Developer Guide - Cloud Watch Logs setup
To verify you could connect to your local broker like this to listen for any message:
mosquitto_sub -h localhost -t yourtopic/#
Now you need to push something to AWS IoT Broker, for example using the AWS IoT Button.
In this case you need to configure your topics to "iotbutton/"
mosquitto_sub -h localhost -t iotbutton/#
{"serialNumber": "Gxxx", "batteryVoltage": "1650mV", "clickType": "SINGLE"}
{"serialNumber": "Gxxx", "batteryVoltage": "1625mV", "clickType": "DOUBLE"}
{"serialNumber": "Gxxx", "batteryVoltage": "1572mV", "clickType": "LONG"}
The message flow is now:
AWS IoT Button -> AWS IoT Broker -> Mosquitto Brigde -> Mosquitto Broker -> mosquitto_sub
I hope this is somewhat usefull, especially the bridge configuration part. It took me a while to find out the correct settings to let the bridge talk to AWS IoT because of the limitations.
Have fun exploring AWS IoT with your existing data.
The openHAB use case is going to be published later.
Bests
Jens