How do you connect to AWS IoT and pub/sub MQTT messages using Toit?
I was able to follow the MQTT tutorial on the Toit Docs site (https://docs.toit.io/tutorials/mqtt/#tls), which worked great for non-TLS between my ESP32 running Toit and a Raspberry Pi running mosquitto.
However, I am now trying to to pub/sub messages with AWS IoT Core. As instructed in the TLS section of the Toit MQTT tutorial I have installed the Toit root certs package:
jag pkg install github.com/toitware/toit-cert-roots@v1
I changed --root_certificates=[certificate_roots.ISRG_ROOT_X1]
to --root_certificates=[certificate_roots.AMAZON_ROOT_CA_1]
when creating the transport
. However, it is not clear how or where to specify the device certificate and the private key.
In the Toit MQTT Library documentation (https://pkg.toit.io/github.com/toitware/mqtt@2.2.0/docs/mqtt/class-TcpTransport), it shows how you can specify a parameter called --certificate
of type Certificate
.
tls network/Interface --host/string --port/int= --root_certificates/List= --server_name/string= --certificate/Certificate= -> TcpTransport
Certificate
object?--certificate
two times?You should have a client certificate and a client key. These are typically given by Amazon as "device_name.cert.pem", and "device-name.private.key"
The certificate starts with -----BEGIN CERTIFICATE-----
and the key with -----BEGIN RSA PRIVATE KEY-----
.
Let's assume that the certificate string is in variable CLIENT_CERTIFICATE_DER
and the key in variable CLIENT_KEY_DER
. The "DER" stands for the "distinguished encoding rules".
You can then create a transport for AWS as follows:
import certificate_roots
import net
import net.x509
import mqtt
import mqtt.transport as mqtt
import tls
HOST ::= "<YOUR AMAZON HOST>"
PORT ::= 8883
ROOT_CERTIFICATE ::= certificate_roots.AMAZON_ROOT_CA_1
CLIENT_CERTIFICATE_DER ::= """
-----BEGIN CERTIFICATE-----
<YOUR CERTIFICATE>
-----END CERTIFICATE-----
"""
CLIENT_KEY_DER ::= """
-----BEGIN RSA PRIVATE KEY-----
<YOUR KEY>
-----END RSA PRIVATE KEY-----
"""
create_aws_transport network/net.Interface -> mqtt.Transport:
parsed := x509.Certificate.parse CLIENT_CERTIFICATE_DER
client_certificate := tls.Certificate parsed CLIENT_KEY_DER
return mqtt.TcpTransport.tls network
--host=HOST
--port=PORT
--root_certificates=[ROOT_CERTIFICATE]
--certificate=client_certificate
You can then connect to the broker as follows:
main:
network := net.open
transport := create_aws_transport network
client := mqtt.Client --transport=transport
options := mqtt.SessionOptions
--client_id="<YOUR CLIENT ID>"
client.start --options=options
client.publish "YOUR_TOPIC" "hello".to_byte_array
client.close
network.close
Remember that AWS has policies for each device that restrict the allowed client ids and the allowed topics.
If you get an "invalid packet kind: 0", then you are using a client_id that isn't allowed by your policy.