- Newest
- Most votes
- Most comments
I would like to add to this question based on my experience with this same issue. This topic not easy to find up-to-date solutions for, when it comes to the problem of using the most recent MicroPython umqtt library (1.4.0) with AWS IoT Core. Most YouTube, Raspberry Pi community guidance/examples are for an older version of umqtt. I hope this helps others who are trying to google for a solution.
Context I have a Raspberry Pi Pico W connected to a development board (BCRobot Pico-Irrigation), which acts as an automated irrigation system. I was trying to use IoT Core to communicate with this system and receive sensor data using MQTT.
MicroPython Version: v1.23.0 MQTT Library: v1.4.0
Issue Using the above configuration for SSLContext from muimu and the AWS community post linked by Max, I was still unable to get the Pico W to connect to my AWS endpoint. The response from the endpoint was zero bytes in length causing an error in the umqtt library.
I had converted the certificates correctly, as when verified using openssl s_client, the connection was fine.
I did notice that the s_client output indicated TLS v1.3, with a cipher of TLS_AES_128_GCM_SHA256. When using MicroPython ssl libray - SSLContext.get_ciphers(), I could not see this cipher enabled and I had no luck enabling it.
I don't know enough about TLS or SSL to know whether I am making an incorrect assumption about my connection issues, and so I defer to the AWS community members who may have more experienced input.
Solution The following steps worked for me:
On the AWS Console -> AWS IoT:
-
Settings -> Device data endpoint I changed the 'Select security policy' dropdown option to 'IoTSecurityPolicy_TLS12_1_2_2022_10' for my endpoint. Did this make a difference?
-
Security -> Policies Created a new policy from scratch (just to be sure). I made sure I had; iot:Connect, iot:Publish, iot:Subscribe, iot:Receive allowed for my testing purposes.
-
All Devices -> Things - Create Thing I created a new 'thing' from scratch and selected the aforementioned policy in the new thing creation options.
-
Downloaded The Certificates I downloaded all certificates during the 'thing' creation and converted the private key and certificate to DER using the openssl commands below (no change from previous attempts here):
openssl pkey -in .\xxxxxx-private.pem.key -out irrigation-control.private.key.der -outform DER openssl x509 -in .\xxxxxx-certificate.pem.crt -out irrigation-control.certificate.der -outform DER
I tested the commands using the 'AmazonRootCA1.pem' with the converted DER format private key and certificate using the openssl commands below:
openssl s_client -connect xxxxxxxxxxxxxxx-ats.iot.eu-west-1.amazonaws.com:8883 -CAfile .\AmazonRootCA1.pem -cert .\irrigation-control.certificate.der -certform DER -key .\irrigation-control.private.key.der -keyform DER
I downloaded the Amazon Root CA 1 in DER format manually, from https://www.amazontrust.com/repository/. I wasn't sure whether previously, I was converting the original from PEM to DER correctly, and so I chose this safer option.
After the above, I was finally able to get a connection and see incoming messages on the MQTT test client.
Code example below:
import ntptime import ssl # after WiFi connection logic... ntptime.settime() MQTT_ENDPOINT = b"xxxxxxxxxxxxxxx-ats.iot.xx-xxxx-1.amazonaws.com" MQTT_CLIENT_ID = b"xxxxxx-xxxxxx" with open("certs/irrigation-control.private.key.der", "rb") as f: PRIVATE_KEY_DER = f.read() with open("certs/irrigation-control.certificate.der", "rb") as f: CERT_DER = f.read() # .cer file is DER format from https://www.amazontrust.com/repository/ with open("certs/AmazonRootCA1.cer", "rb") as f: CA_DER = f.read() context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED context.load_cert_chain(CERT_DER, PRIVATE_KEY_DER) context.load_verify_locations(cadata=CA_DER) mqtt_client = MQTTClient( client_id=MQTT_CLIENT_ID, server=MQTT_ENDPOINT, port=8883, keepalive=5000, ssl=context, ) mqtt_client.connect() print("Connected to AWS IoT...") mqtt_client.set_callback(subscription_cb) mqtt_client.subscribe("sdk/test/python") while True: try: mqtt_client.publish(topic=b"test/irrigation", msg=b"HELLO", qos=0) sleep(5) except KeyboardInterrupt: print("Execution interrupted")
Looking at your code, you seem to have copy-pasted it from this AWS Community Article:
https://community.aws/concepts/getting-started-with-pico-w-iot-core
There is a good walk-through in this article on how to create a thing, setup the IAM policies, download the certificates and how to copy them to the Raspberry device. If you follow these - you should be able to get this working as intended.
If you use the latest version of umqtt.simple, i.e., 1.4.0, you need to modify the way to deal with ssl.
- You can no longer include 'ssl_params' as a parameter for MQTTClient.
- You need to set an instance of 'ssl.SSLContext' to 'ssl', not a boolean.
- In addition, you have to set time by ntp.
Setting time:
import ntptime ntptime.settime()
Preparing SSLContext:
import ssl from umqtt.simple import MQTTClient context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(cafile='ca.der') context.load_cert_chain('cert.der', 'key.der')
When you convert the PEM key to a DER format, you need to specify 'pkey', instead of 'rsa'.
openssl pkey -in key.pem -out key.der -outform DER
Now you can get the instance of the client and connect to AWS IoT Core.
mqtt = MQTTClient( client_id=CLIENT_ID, server=AWS_ENDPOINT, port=8883, keepalive=5000, ssl = context ) mqtt.connect()
Relevant content
- asked 2 years ago
- AWS OFFICIALUpdated a year ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 5 months ago
- AWS OFFICIALUpdated 10 months ago
FYI: I didn't choose 'security policy' manually.
IoTSecurityPolicy_TLS13_1_2_2022_10
was shown in my Settings of AWS Console.According to the following URL, it is the default and I can connect with it. https://docs.aws.amazon.com/iot/latest/developerguide/transport-security.html#tls-policy-table
Anyway, congratulations for succeeding in MQTT connection!