Tutorial: Use TLS in Python for MQTT
If you are familiar with the Python Paho MQTT library, implementing TLS is simple.
Ensure you have a server certificate file created and configured on the FairCom server.
You must create a separate server certificate for each computer that runs a FairCom server. Each FairCom server must be configured to use the appropriate server certificate for the computer on which it runs
Ensure you have client certificate file created and ready to use in this Python program.
The client certificate file allows the Python program to identify itself to the FairCom server. Each Python program that wants to use a certificate must be configured to send the certificate to the server. When the FairCom server is not configured with the CA certificate, do not use a client certificate in a Python program.
Ensure you meet the prerequisites before this procedure.
Configure the
MQTTS
listener in theservices.json
file to use your CA certificate, server certificate, and private key.Ensure the
"enabled"
property is set totrue
.Update the
"tls"
object:Update the
"certificateFilename"
property value to the certificate you obtained for this FairCom server.Add a
"privateKeyFilename"
property and set it to the private key for this FairCom server.Add a
"certificateAuthoritiesFilename"
property and set it to the path and filename containing CA certificate.Note
This is the certificate from the CA that signed the server certificate.
Save any changes.
Restart the server for the changes to take effect.
MQTTS
listener{ "serviceName": "mqtts8883", "description": "Port 8883 using TLS-secured MQTTS protocol for the MQTT broker on all TCP/IP addresses bound to this server", "port": 8883, "protocol": "mqtts", "enabled": true, "tls": { "certificateAuthoritiesFilename": "C:/Certificates/ca.crt", "certificateFilename": "C:/Certificates/server.crt", "privateKeyFilename": "C:/Certificates/server.key" } },
MQTTWSS
listener{ "serviceName": "mqttwss9002", "description": "Port 9002 using TLS-secured WebSocket protocol for the MQTT broker on all TCP/IP addresses bound to this server", "port": 9002, "protocol": "mqttwss", "enabled": true, "tls": { "certificateAuthoritiesFilename": "C:/Certificates/ca.crt", "certificateFilename": "C:/Certificates/server.crt", "privateKeyFilename": "C:/Certificates/server.key" } }
Ensure you meet the prerequisites before this procedure.
Update the
"port"
property value to the TLS port used by your broker.Call
tls_set()
on yourpaho.mqtt.client
class object with the following parameters (see Example program):ca_certs
certfile
keyfile
Ensure you meet the prerequisites before this procedure.
Create a
callback
function that will print any messages received using the following code:def message_callback( message_client, userdata, message ): print( message.payload.decode( 'utf8' ) )
Define a client using the following code:
Note
To use a secure WebSocket, this call only needs the additional parameter of
transport = 'websockets'
.mqtts_client = mqtt.Client( client_id = "MQTTS Client ID" )
Enable TLS by calling
tls_set()
on the newly created client using the following code:mqtts_client.tls_set( ca_certs = "/Certificates/ca.crt", certfile = "/Certificates/client.crt", keyfile = "/Certificates/client.key" )
Assign the message callback to the client using the following code:
Note
There are many callbacks in the Paho library, including
on_connect
,on_connect_fail
,on_disconnect
,on_message
,on_publish
,on_subscribe
,on_unsubscribe
,on_log
,on_socket_open
,on_socket_close
,on_socket_register_write
,on_socket_unregister_write
.mqtts_client.on_message = message_callback
Call
loop_start()
on the client to begin processing MQTT events using the following code:mqtts_client.loop_start()
Connect the client and server using the following code:
Note
The port is set to
8883
. This must match the port configured inservices.json
. The broker address must also match the address in its certificate.mqtts_client.connect( "MyServer.local", port = 8883 )
Wait a few seconds or use the
on_connect
callback as a guide to when the connection has been made.Note
The connection will appear instantaneously, but work is happening in the background.
Subscribe to a topic of your choice using the following code:
mqtts_client.subscribe( "test/MqttsTopic" )
Publish to your chosen topic using the following code:
mqtts_client.publish( "test/MqttsTopic", "Simple MQTTS message" )
Implement a simple non-blocking delay using the following code:
Note
Do this step because even though the message will arrive in a few milliseconds, your code could finish before the message arrives.
count = 0while count < 5: time.sleep( 1 ) count += 1
Observe the message:
Note
Receiving the message means your client was able to subscribe and publish to your broker using TLS for encryption and authentication.
Simple MQTTS message
Close the connection using the following code:
mqtts_client.unsubscribe( "test/MqttsTopic" ) mqtts_client.disconnect() mqtts_client.loop_stop()
import time import paho.mqtt.client as mqtt def message_callback( message_client, userdata, message ): print( message.payload.decode( 'utf8' ) ) if __name__ == "__main__": mqtts_client = mqtt.Client( client_id = "MQTTS Client ID" ) mqtts_client.tls_set( ca_certs = "/Certificates/ca.crt", certfile = "/Certificates/client.crt", keyfile = "/Certificates/client.key" ) mqtts_client.on_message = message_callback mqtts_client.loop_start() mqtts_client.connect( "MyServer.local", port = 8883 ) time.sleep( 2 ) mqtts_client.subscribe( "test/MqttsTopic" ) mqtts_client.publish( "test/MqttsTopic", "Simple MQTTS message" ) count = 0 while count < 5: time.sleep( 1 ) count += 1 mqtts_client.unsubscribe( "test/MqttsTopic" ) mqtts_client.disconnect() mqtts_client.loop_stop()
import time import paho.mqtt.client as mqtt def message_callback( message_client, userdata, message ): print( message.payload.decode( 'utf8' ) ) if __name__ == "__main__": mqtts_client = mqtt.Client( client_id = "MQTTS Client ID", transport = 'websockets' ) mqtts_client.tls_set( ca_certs = "/Certificates/ca.crt", certfile = "/Certificates/client.crt", keyfile = "/Certificates/client.key" ) mqtts_client.on_message = message_callback mqtts_client.loop_start() mqtts_client.connect( "MyServer.local", port = 9002 ) time.sleep( 2 ) mqtts_client.subscribe( "test/MqttWssTopic" ) mqtts_client.publish( "test/MqttWssTopic", "Simple MQTT WSS message" ) count = 0 while count < 5: time.sleep( 1 ) count += 1 mqtts_client.unsubscribe( "test/MqttWssTopic" ) mqtts_client.disconnect() mqtts_client.loop_stop()