Skip to content

Commit

Permalink
Merge pull request #190 from mathieu1fb/feature/security
Browse files Browse the repository at this point in the history
Java/iot3core: secure message exchanges for user equipment
  • Loading branch information
mathieu1fb authored Oct 24, 2024
2 parents 2eb528a + de073f8 commit 59d2902
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 126 deletions.
78 changes: 29 additions & 49 deletions java/iot3/core/src/main/java/com/orange/iot3core/IoT3Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,51 +31,24 @@ public class IoT3Core {
* Instantiate the IoT3.0 Core SDK.
*
* @param mqttHost MQTT broker address
* @param mqttPort port of the MQTT broker
* @param mqttUsername MQTT username
* @param mqttPassword MQTT password
* @param mqttClientId unique MQTT client ID
* @param ioT3CoreCallback interface to retrieve the different clients outputs
* @param telemetryHost Open Telemetry server address
*/
public IoT3Core(String mqttHost,
String mqttUsername,
String mqttPassword,
String mqttClientId,
IoT3CoreCallback ioT3CoreCallback,
String telemetryHost) {
this(mqttHost,
1883,
8883,
mqttUsername,
mqttPassword,
mqttClientId,
ioT3CoreCallback,
telemetryHost,
-1,
"/telemetry",
"default",
"default");
}

/**
* Instantiate the IoT3.0 Core SDK.
*
* @param mqttHost MQTT broker address
* @param mqttPortTcp TCP port of the MQTT broker
* @param mqttPortTls TLS port of the MQTT broker
* @param mqttUsername MQTT username
* @param mqttPassword MQTT password
* @param mqttClientId unique MQTT client ID
* @param mqttUseTls use TLS for a secure connection with the MQTT broker
* @param ioT3CoreCallback interface to retrieve the different clients outputs
* @param telemetryHost Open Telemetry server address
* @param telemetryPort port of the Open Telemetry server
* @param telemetryEndpoint endpoint of the Open Telemetry server URL
* @param telemetryUsername Open Telemetry username
* @param telemetryPassword Open Telemetry password
*/
public IoT3Core(String mqttHost,
int mqttPortTcp,
int mqttPortTls,
private IoT3Core(String mqttHost,
int mqttPort,
String mqttUsername,
String mqttPassword,
String mqttClientId,
boolean mqttUseTls,
IoT3CoreCallback ioT3CoreCallback,
String telemetryHost,
int telemetryPort,
Expand All @@ -95,12 +68,11 @@ public IoT3Core(String mqttHost,
// instantiate the MQTT client
this.mqttClient = new MqttClient(
mqttHost,
mqttPortTcp,
mqttPortTls,
mqttPort,
mqttUsername,
mqttPassword,
mqttClientId,
null,
mqttUseTls,
new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
Expand Down Expand Up @@ -225,16 +197,24 @@ public void mqttPublish(String topic, String message, boolean retain) {
if(mqttClient != null) mqttClient.publishMessage(topic, message, retain);
}

/**
* Check that the MQTT connection is secured with TLS
*/
public boolean isMqttConnectionSecured() {
if(mqttClient != null) return mqttClient.isConnected() && mqttClient.isConnectionSecured();
else return false;
}

/**
* Build an instance of IoT3Core.
*/
public static class IoT3CoreBuilder {
private String mqttHost;
private int mqttPortTcp;
private int mqttPortTls;
private int mqttPort;
private String mqttUsername;
private String mqttPassword;
private String mqttClientId;
private boolean mqttUseTls;
private IoT3CoreCallback ioT3CoreCallback;
private String telemetryHost;
private int telemetryPort;
Expand All @@ -251,24 +231,24 @@ public IoT3CoreBuilder() {}
* Set the MQTT parameters of your IoT3Core instance.
*
* @param mqttHost the host or IP address of the MQTT broker
* @param mqttPortTcp the TCP port of the MQTT broker
* @param mqttPortTls the TLS port of the MQTT broker
* @param mqttPort the port of the MQTT broker
* @param mqttUsername the username for authentication with the MQTT broker
* @param mqttPassword the password for authentication with the MQTT broker
* @param mqttClientId your client ID
* @param mqttUseTls use TLS for a secure connection with the MQTT broker
*/
public IoT3CoreBuilder mqttParams(String mqttHost,
int mqttPortTcp,
int mqttPortTls,
int mqttPort,
String mqttUsername,
String mqttPassword,
String mqttClientId) {
String mqttClientId,
boolean mqttUseTls) {
this.mqttHost = mqttHost;
this.mqttPortTcp = mqttPortTcp;
this.mqttPortTls = mqttPortTls;
this.mqttPort = mqttPort;
this.mqttUsername = mqttUsername;
this.mqttPassword = mqttPassword;
this.mqttClientId = mqttClientId;
this.mqttUseTls = mqttUseTls;
return this;
}

Expand Down Expand Up @@ -313,11 +293,11 @@ public IoT3CoreBuilder callback(IoT3CoreCallback ioT3CoreCallback) {
public IoT3Core build() {
return new IoT3Core(
mqttHost,
mqttPortTcp,
mqttPortTls,
mqttPort,
mqttUsername,
mqttPassword,
mqttClientId,
mqttUseTls,
ioT3CoreCallback,
telemetryHost,
telemetryPort,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/
package com.orange.iot3core.clients;

import com.hivemq.client.mqtt.MqttClientSslConfig;
import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
import com.hivemq.client.mqtt.datatypes.MqttQos;
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
Expand Down Expand Up @@ -39,24 +38,25 @@ public class MqttClient {
private final MqttCallback callback;
private final OpenTelemetryClient openTelemetryClient;

private boolean tlsConnection = false;
private final boolean useTls;

public MqttClient(String serverHost,
int tcpPort,
int tlsPort,
int serverPort,
String username,
String password,
String clientId,
MqttClientSslConfig sslConfig,
boolean useTls,
MqttCallback callback,
OpenTelemetryClient openTelemetryClient) {
this.callback = callback;
this.openTelemetryClient = openTelemetryClient;
this.useTls = useTls;

Mqtt5ClientBuilder mqttClientBuilder = com.hivemq.client.mqtt.MqttClient.builder()
.useMqttVersion5()
.identifier(clientId)
.serverHost(serverHost)
.serverPort(serverPort)
.addDisconnectedListener(context1 -> {
LOGGER.log(Level.INFO, "Disconnected from MQTT broker " + serverHost);
callback.connectionLost(context1.getCause());
Expand All @@ -73,14 +73,10 @@ public MqttClient(String serverHost,
.applySimpleAuth();
}

if(sslConfig == null) {
mqttClient = mqttClientBuilder.serverPort(tcpPort)
.buildAsync();
if(useTls) {
mqttClient = mqttClientBuilder.sslWithDefaultConfig().buildAsync();
} else {
mqttClient = mqttClientBuilder.serverPort(tlsPort)
.sslConfig(sslConfig)
.buildAsync();
tlsConnection = true;
mqttClient = mqttClientBuilder.buildAsync();
}

// single callback for processing messages received on subscribed topics
Expand All @@ -93,13 +89,12 @@ public void disconnect() {
if(mqttClient != null) {
mqttClient.disconnect().whenComplete((mqtt5DisconnectResult, throwable) -> {
if(throwable != null) {
LOGGER.log(Level.WARNING, "Error during disconnection");
LOGGER.log(Level.WARNING, "Error during disconnection: " + throwable.getMessage());
} else {
LOGGER.log(Level.INFO, "Disconnected");
}
});
}
tlsConnection = false;
}

public void connect() {
Expand All @@ -108,7 +103,7 @@ public void connect() {
.send()
.whenComplete((connAck, throwable) -> {
if(throwable != null) {
LOGGER.log(Level.INFO, "Error during connection to the server");
LOGGER.log(Level.INFO, "Error during connection to the server: " + throwable.getMessage());
} else {
LOGGER.log(Level.INFO, "Success connecting to the server");
}
Expand All @@ -123,7 +118,7 @@ public void subscribeToTopic(String topic) {
.send()
.whenComplete((subAck, throwable) -> {
if (throwable != null) {
LOGGER.log(Level.WARNING, "Subscribed fail!");
LOGGER.log(Level.WARNING, "Subscription failed: " + throwable.getMessage());
} else {
LOGGER.log(Level.FINE, "Subscribed!");
}
Expand All @@ -142,7 +137,7 @@ public void unsubscribeFromTopic(String topic) {
.send()
.whenComplete((subAck, throwable) -> {
if (throwable != null) {
LOGGER.log(Level.WARNING, "Unsubscribed fail!");
LOGGER.log(Level.WARNING, "Unsubscription failed: " + throwable.getMessage());
} else {
LOGGER.log(Level.INFO, "Unsubscribed!");
}
Expand Down Expand Up @@ -270,7 +265,7 @@ public boolean isConnected() {
}

public boolean isConnectionSecured() {
return isConnected() && tlsConnection;
return isConnected() && useTls;
}

public boolean isValidMqttPubTopic(String topic) {
Expand Down
13 changes: 8 additions & 5 deletions java/iot3/examples/src/main/java/com/orange/Iot3CoreExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public class Iot3CoreExample {

// MQTT parameters
private static final String EXAMPLE_MQTT_HOST = "mqtt_host";
private static final int EXAMPLE_MQTT_PORT_TCP = 1883;
private static final int EXAMPLE_MQTT_PORT_TLS = 8883;
private static final int EXAMPLE_MQTT_PORT = 1883;
private static final String EXAMPLE_MQTT_USERNAME = "mqtt_username";
private static final String EXAMPLE_MQTT_PASSWORD = "mqtt_password";
private static final String EXAMPLE_MQTT_CLIENT_ID = "mqtt_client_id";
private static final boolean EXAMPLE_MQTT_USE_TLS = true;
// OpenTelemetry parameters
private static final String EXAMPLE_OTL_HOST = "telemetry_host";
private static final int EXAMPLE_OTL_PORT = 4318;
Expand All @@ -29,11 +29,11 @@ public static void main(String[] args) {
// instantiate IoT3Core and its callback
ioT3Core = new IoT3Core.IoT3CoreBuilder()
.mqttParams(EXAMPLE_MQTT_HOST,
EXAMPLE_MQTT_PORT_TCP,
EXAMPLE_MQTT_PORT_TLS,
EXAMPLE_MQTT_PORT,
EXAMPLE_MQTT_USERNAME,
EXAMPLE_MQTT_PASSWORD,
EXAMPLE_MQTT_CLIENT_ID)
EXAMPLE_MQTT_CLIENT_ID,
EXAMPLE_MQTT_USE_TLS)
.telemetryParams(EXAMPLE_OTL_HOST,
EXAMPLE_OTL_PORT,
EXAMPLE_OTL_ENDPOINT,
Expand Down Expand Up @@ -78,6 +78,9 @@ public void mqttUnsubscriptionComplete(Throwable unsubscribeFailure) {
}

private static void onConnectionComplete() {
// Check if MQTT connection is secured
if(ioT3Core.isMqttConnectionSecured()) System.out.println("MQTT connection is SECURED");
else System.out.println("MQTT connection is NOT SECURED");
// subscribe to the root test topic and to all iot3 topics using the wildcard #
ioT3Core.mqttSubscribe("test");
ioT3Core.mqttSubscribe("test/iot3/#");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,37 @@

public class Iot3MobilityExample {

private static final String EXAMPLE_HOST = "host";
private static final String EXAMPLE_USERNAME = "username";
private static final String EXAMPLE_PASSWORD = "password";
private static final String EXAMPLE_UUID = "uuid";
private static final String EXAMPLE_CONTEXT = "context";
private static final String EXAMPLE_TELEMETRY_HOST = "telemetry_host";
// MQTT parameters
private static final String EXAMPLE_MQTT_HOST = "mqtt_host";
private static final int EXAMPLE_MQTT_PORT = 1883;
private static final String EXAMPLE_MQTT_USERNAME = "mqtt_username";
private static final String EXAMPLE_MQTT_PASSWORD = "mqtt_password";
private static final boolean EXAMPLE_MQTT_USE_TLS = false;
// OpenTelemetry parameters
private static final String EXAMPLE_OTL_HOST = "telemetry_host";
private static final int EXAMPLE_OTL_PORT = 4318;
private static final String EXAMPLE_OTL_ENDPOINT = "/telemetry/endpoint";
private static final String EXAMPLE_OTL_USERNAME = "telemetry_username";
private static final String EXAMPLE_OTL_PASSWORD = "telemetry_password";

private static IoT3Mobility ioT3Mobility;

public static void main(String[] args) {
// instantiate IoT3Mobility and its callback
ioT3Mobility = new IoT3Mobility(
EXAMPLE_HOST,
EXAMPLE_USERNAME,
EXAMPLE_PASSWORD,
EXAMPLE_UUID, // serves to identify the road user, app or infrastructure
EXAMPLE_CONTEXT, // serves as the root of the MQTT mobility topics
new IoT3MobilityCallback() {
ioT3Mobility = new IoT3Mobility.IoT3MobilityBuilder(EXAMPLE_UUID, EXAMPLE_CONTEXT)
.mqttParams(EXAMPLE_MQTT_HOST,
EXAMPLE_MQTT_PORT,
EXAMPLE_MQTT_USERNAME,
EXAMPLE_MQTT_PASSWORD,
EXAMPLE_MQTT_USE_TLS)
.telemetryParams(EXAMPLE_OTL_HOST,
EXAMPLE_OTL_PORT,
EXAMPLE_OTL_ENDPOINT,
EXAMPLE_OTL_USERNAME,
EXAMPLE_OTL_PASSWORD)
.callback(new IoT3MobilityCallback() {
@Override
public void connectionLost(Throwable cause) {
System.out.println("MQTT Connection lost...");
Expand All @@ -57,8 +70,8 @@ public void connectionLost(Throwable cause) {
public void connectComplete(boolean reconnect, String serverURI) {
System.out.println("MQTT connection complete: " + serverURI);
}
},
EXAMPLE_TELEMETRY_HOST);
})
.build();

// set the RoadHazardCallback to be informed of road hazards in the corresponding Region of Interest (RoI)
ioT3Mobility.setRoadHazardCallback(new IoT3RoadHazardCallback() {
Expand Down Expand Up @@ -90,13 +103,13 @@ public void newRoadUser(RoadUser roadUser) {
// RoadUser is a simple object provided by IoT3Mobility
System.out.println("New Road User: " + roadUser.getUuid());
LatLng position = roadUser.getPosition();
System.out.println("Road User position: " + position.toString());
System.out.println("Road User position: " + position);
// the CAM on which this object is based can still be accessed
CAM originalCam = roadUser.getCam();
double latitude = originalCam.getBasicContainer().getPosition().getLatitudeDegree();
double longitude = originalCam.getBasicContainer().getPosition().getLongitudeDegree();
LatLng camPosition = new LatLng(latitude, longitude);
System.out.println("CAM position: " + camPosition.toString());
System.out.println("CAM position: " + camPosition);
}

@Override
Expand Down
Loading

0 comments on commit 59d2902

Please sign in to comment.