Certificate based MQTT (AWS IoT) trouble with changed umqtt
-
Hi,
unfortunately the micropython certificate handling for MQTT has been changed last year. good description
Here is the new way to do it:# Create an SSL context context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED # Load certificates context.load_verify_locations(cafile='/flash/certificate/ca.der') context.load_cert_chain('/flash/certificate/cert.der', '/flash/certificate/key.der') mqtt = MQTTClient(client_id=client, server=endpoint, port=8883, keepalive=1200, ssl=context) print("Connecting to AWS IoT...") mqtt.connect() print("Done")
While the code and certificates work fine on ESP32-S3 Micropython they result in the following error on uiflow2
Traceback (most recent call last): File "<stdin>", line 74, in <module> File "<stdin>", line 52, in mqtt_connect File "/flash/libs/umqttn/simple.py", line 69, in connect File "ssl.py", line 1, in wrap_socket ValueError: The certificate validity has expired
I triple checked the certificate validity..
Next suspect would be an incorrect system time. Therfore I set the time as follows before attempting to initialize a mqtt connection:sta_if = network.WLAN(network.STA_IF) sta_if.active(True) if sta_if.isconnected(): sta_if.disconnect() sta_if.connect(wifi_ssid, wifi_password) while not sta_if.isconnected(): utime.sleep(1) print("Connecting...") print("Connected:", sta_if.ifconfig()) print(f"time before NTP settime {time.localtime()}") ntptime.settime() print(f"time after NTP settime {time.localtime()}") import machine rtc = machine.RTC() # Set manually to a known correct UTC date/time: (year, month, day, weekday, hour, minute, second, microsecond) rtc.datetime((2025, 3, 14, 1, 14, 0, 0, 0)) print("Manually set time:", machine.RTC().datetime())
Still I get the same error:
Connecting... Connecting... Connecting... Connecting... Connected: ('192.168.5.0', '255.255.252.0', '192.168.4.1', '192.168.4.1') time before NTP settime (2025, 3, 14, 12, 8, 44, 5, 72) time after NTP settime (2025, 3, 14, 12, 8, 45, 5, 72) Manually set time: (2025, 3, 14, 5, 14, 0, 0, 67) Connecting to AWS IoT... MQTT Connection failed: The certificate validity has expired Traceback (most recent call last): File "<stdin>", line 79, in <module> File "<stdin>", line 57, in mqtt_connect File "/flash/libs/umqttn/simple.py", line 69, in connect File "ssl.py", line 1, in wrap_socket ValueError: The certificate validity has expired
I used the micropython/umqtt.simple/umqtt/simple.py implementation installed as module umqttn in the /flash/libs folder. It differs from the m5stack implementation (which is currently broken for certificate based MQTT due to the described changes in Micropython).
At this point I wonder why the same code (umqtt.simple, demo-code, exactly the same certificate files) work on an UMFeatherS2 MicroPython v1.24.1 but fail on MicroPython v1.24.0-dirty on 2025-03-06; M5STACK CoreS3 with ESP32S3.
I would happy for any hint on how to solve this.
-
@sistar_hh said in Certificate based MQTT (AWS IoT) trouble with changed umqtt:
Hi,
unfortunately the micropython certificate handling for MQTT has been changed last year. good description
Here is the new way to do it:Create an SSL context
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED # Load certificates context.load_verify_locations(cafile='/flash/certificate/ca.der') context.load_cert_chain('/flash/certificate/cert.der', '/flash/certificate/key.der') mqtt = MQTTClient(client_id=client, server=endpoint, port=8883, keepalive=1200, ssl=context) print("Connecting to AWS IoT...") mqtt.connect() print("Done")
While the code and certificates work fine on ESP32-S3 Micropython they result in the following error on uiflow2
Traceback (most recent call last):
File "<stdin>", line 74, in <module>
File "<stdin>", line 52, in mqtt_connect
File "/flash/libs/umqttn/simple.py", line 69, in connect
File "ssl.py", line 1, in wrap_socket
ValueError:
The certificate validity has expired
I triple checked the certificate validity..
Next suspect would be an incorrect system time. Therfore I set the time as follows before attempting to initialize a mqtt connection:sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
if sta_if.isconnected():
sta_if.disconnect()
sta_if.connect(wifi_ssid, wifi_password)
while not sta_if.isconnected():
utime.sleep(1)
print("Connecting...")
print("Connected:", sta_if.ifconfig())print(f"time before NTP settime {time.localtime()}")
ntptime.settime()
print(f"time after NTP settime {time.localtime()}")
import machine
rtc = machine.RTC()Set manually to a known correct UTC date/time: (year, month, day, weekday, hour, minute, second, microsecond)
rtc.datetime((2025, 3, 14, 1, 14, 0, 0, 0))
print("Manually set time:", machine.RTC().datetime())
Still I get the same error:Connecting...
Connecting...
Connecting...
Connecting...
Connected: ('192.168.5.0', '255.255.252.0', '192.168.4.1', '192.168.4.1')
time before NTP settime (2025, 3, 14, 12, 8, 44, 5, 72)
time after NTP settime (2025, 3, 14, 12, 8, 45, 5, 72)
Manually set time: (2025, 3, 14, 5, 14, 0, 0, 67)
Connecting to AWS IoT...
MQTT Connection failed:
The certificate validity has expiredTraceback (most recent call last):
File "<stdin>", line 79, in <module>
File "<stdin>", line 57, in mqtt_connect
File "/flash/libs/umqttn/simple.py", line 69, in connect
File "ssl.py", line 1, in wrap_socket
ValueError:
The certificate validity has expired
I used the micropython/umqtt.simple/umqtt/simple.py implementation installed as module umqttn in the /flash/libs folder. It differs from the m5stack implementation (which is currently broken for certificate based MQTT due to the described changes in Micropython).At this point I wonder why the same code (umqtt.simple, demo-code, exactly the same certificate files) work on an UMFeatherS2 MicroPython v1.24.1 but fail on MicroPython v1.24.0-dirty on 2025-03-06; M5STACK CoreS3 with ESP32S3.
I would happy for any hint on how to solve this.
Aha! When trying the following change:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.verify_mode = ssl.CERT_OPTIONAL # Instead of CERT_REQUIRED
I successfully connected!