MQTT with tls/ssl towards AWS

Hi

I have been working my head around setting up MQTT connection for publishing onto AWS cloud. Starting point was the MQTT controller. It works like a charm when testing locally, unencrypted, against a mosquitto server running locally but I have no success at all when using the TLS/SSL approach against the AWS cloud.

Do anyone have experience to give me a hint?

The entire setup on the AWS side is working with my certificates. It is validated using the AWS python example, using the MQTT explorer tool and I have run this boiled down java example : testMQTT.java

All of these with success.

When running the controller it initially reports success on connection - but publish fails.

Any thoughts?

This is the error messages received:

2024-04-17T14:43:32,838 [75cc58a)] INFO  [onent.AbstractOpenemsComponent] [ctrlControllerApiMqtt] Activate Controller.Api.MQTT
2024-04-17T14:43:33,701 [Worker-0] INFO  [i.mqtt.SendChannelValuesWorker] [ctrlControllerApiMqtt] Error while sending MQTT topics: ctrlApiWebsocket0/_PropertyId, ctrlApiWebsocket0/_PropertyPort, ctrlApiWebsocket0/State, ctrlApiW...
2024-04-17T14:43:33,775 [thread-1] INFO  [api.mqtt.ControllerApiMqttImpl] [ctrlControllerApiMqtt] Connected to MQTT Broker [ssl://aq4iaa6cr629u-ats.iot.eu-central-1.amazonaws.com:8883]
2024-04-17T14:43:34,709 [Worker-0] INFO  [i.mqtt.SendChannelValuesWorker] [ctrlControllerApiMqtt] Successfully sent MQTT topics: ctrlApiWebsocket0/_PropertyId, ctrlApiWebsocket0/_PropertyPort, ctrlApiWebsocket0/State, ctrlApiW...
2024-04-17T14:43:35,682 [Worker-0] INFO  [api.mqtt.ControllerApiMqttImpl] [ctrlControllerApiMqtt] Client is not connected
2024-04-17T14:43:35,683 [Worker-0] INFO  [api.mqtt.ControllerApiMqttImpl] [ctrlControllerApiMqtt] Client is not connected
2024-04-17T14:43:35,683 [Worker-0] INFO  [i.mqtt.SendChannelValuesWorker] [ctrlControllerApiMqtt] Error while sending MQTT topics: _cycle/MeasuredCycleTime
2024-04-17T14:43:36,681 [Worker-0] INFO  [i.mqtt.SendChannelValuesWorker] [ctrlControllerApiMqtt] Successfully sent MQTT topics: _cycle/MeasuredCycleTime
2024-04-17T14:43:37,680 [Worker-0] INFO  [api.mqtt.ControllerApiMqttImpl] [ctrlControllerApiMqtt] Client is not connected

Update.

I believe the issue is reading and handling of the different keys. The AWS log gives me authorization error.

image

I have tried different versions of “pruning” the keys when stored in the config file without success. I was hoping the issue was related to differences between interpretation of line ending (newline + carriage return for Windows versus newline for linux).

Any success stories would be welcome :slight_smile:

While I have no experiences with openEMS mqtt I have experienced the joy of utilizing AWS MQTT service without their sdk. In order to plug stock java client you need to configure SSL/TLS socket factory. Given that your log indicate topic I believe that this part works.
The second part is security policy attached to certificate/credentials. It needs to permit writing to certain topics. Have you done these steps?

By default certificates provisioned through AWS wizzard give you permissions to publish only to sdk/java or sdk/test/java topics. I might look for my notes on how to adjust these policies.

Thank you for the feedback :slight_smile:
I opened up the AWS policies to wildcard publish/subscribe and I am able to publish to the topics used by EMS when using one of the other clients.

The controller builds a socketfactory through io.openems.edge.controller.api.mqtt.MqttUtils.createSslSocketFactory called by io.openems.edge.controller.api.mqtt.ControllerApiMqttImpl.mqttClient.

I think I tracked down some of the headache to passing the different keys and certificates. I have now changed the approach to read the files rather than copy/paste the keys into the config. With this change, I am now successfully connecting but still get an error on publish.

UPDATE: Reasonable success - messages arrives at AWS

The changes implemented:

  1. Read certificate files - as indicated in previous post
  2. Retainflag has to be false - I do not yet understand why. More digging will probably follow.

In: io/openems/edge/controller/api/mqtt/ControllerApiMqttImpl.java

Changed:
protected boolean publish(String subTopic, String message, int qos, boolean retained, MqttProperties properties) { //TODO Figure out why retained must be false for operation with AWS retained = false;

Why false May Be Required
Your specific case where setting retain to false is required for successful operation with AWS IoT might be influenced by one or more of the following:

  • Policy and Configuration: AWS IoT policies might restrict or handle retained messages differently. For example, if the policy does not allow for message retention, attempting to publish a retained message could result in an error or message rejection.

  • Operational Best Practices: AWS may recommend against using the retain flag in certain scenarios to ensure that clients always receive the most current and relevant data without the risk of acting on outdated information.

Investigating Further
To understand why this is necessary in your specific scenario, you can:

  • Review AWS Documentation: Check AWS IoT documentation for any notes on the retain flag and how it affects message publishing. This could provide more clarity and perhaps suggest different configurations or setups that align with AWS best practices and limitations.