diff --git a/application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java index d059ea1449..25df3bee00 100644 --- a/application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java +++ b/application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java @@ -26,13 +26,13 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClasspathSuite.ClassnameFilters({ -// "org.thingsboard.server.transport.*.rpc.sql.*Test", -// "org.thingsboard.server.transport.*.telemetry.timeseries.sql.*Test", -// "org.thingsboard.server.transport.*.telemetry.attributes.sql.*Test", -// "org.thingsboard.server.transport.*.attributes.updates.sql.*Test", -// "org.thingsboard.server.transport.*.attributes.request.sql.*Test", -// "org.thingsboard.server.transport.*.claim.sql.*Test", -// "org.thingsboard.server.transport.*.provision.sql.*Test", + "org.thingsboard.server.transport.*.rpc.sql.*Test", + "org.thingsboard.server.transport.*.telemetry.timeseries.sql.*Test", + "org.thingsboard.server.transport.*.telemetry.attributes.sql.*Test", + "org.thingsboard.server.transport.*.attributes.updates.sql.*Test", + "org.thingsboard.server.transport.*.attributes.request.sql.*Test", + "org.thingsboard.server.transport.*.claim.sql.*Test", + "org.thingsboard.server.transport.*.provision.sql.*Test", "org.thingsboard.server.transport.lwm2m.*Test" }) public class TransportSqlTestSuite { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 90b926e78a..6db6e24f91 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -60,6 +60,53 @@ import java.util.concurrent.ScheduledExecutorService; @DaoSqlTest public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { + protected final String TRANSPORT_CONFIGURATION = "{\n" + + " \"type\": \"LWM2M\",\n" + + " \"observeAttr\": {\n" + + " \"keyName\": {\n" + + " \"/3_1.0/0/9\": \"batteryLevel\"\n" + + " },\n" + + " \"observe\": [],\n" + + " \"attribute\": [\n" + + " ],\n" + + " \"telemetry\": [\n" + + " \"/3_1.0/0/9\"\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " },\n" + + " \"bootstrap\": {\n" + + " \"servers\": {\n" + + " \"binding\": \"U\",\n" + + " \"shortId\": 123,\n" + + " \"lifetime\": 300,\n" + + " \"notifIfDisabled\": true,\n" + + " \"defaultMinPeriod\": 1\n" + + " },\n" + + " \"lwm2mServer\": {\n" + + " \"host\": \"localhost\",\n" + + " \"port\": 5686,\n" + + " \"serverId\": 123,\n" + + " \"serverPublicKey\": \"\",\n" + + " \"bootstrapServerIs\": false,\n" + + " \"clientHoldOffTime\": 1,\n" + + " \"bootstrapServerAccountTimeout\": 0\n" + + " },\n" + + " \"bootstrapServer\": {\n" + + " \"host\": \"localhost\",\n" + + " \"port\": 5687,\n" + + " \"serverId\": 111,\n" + + " \"securityMode\": \"NO_SEC\",\n" + + " \"serverPublicKey\": \"\",\n" + + " \"bootstrapServerIs\": true,\n" + + " \"clientHoldOffTime\": 1,\n" + + " \"bootstrapServerAccountTimeout\": 0\n" + + " }\n" + + " },\n" + + " \"clientLwM2mSettings\": {\n" + + " \"clientOnlyObserveAfterConnect\": 1\n" + + " }\n" + + "}"; + protected DeviceProfile deviceProfile; protected ScheduledExecutorService executor; protected TbTestWebSocketClient wsClient; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/NoSecLwM2MIntegrationTest.java index 2021dd839c..7d173e61d9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/NoSecLwM2MIntegrationTest.java @@ -22,6 +22,7 @@ import org.junit.Assert; import org.junit.Test; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials; import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityDataPageLink; import org.thingsboard.server.common.data.query.EntityDataQuery; @@ -36,7 +37,6 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate; import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; -import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials; import java.util.Collections; import java.util.List; @@ -46,60 +46,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { - protected final String TRANSPORT_CONFIGURATION = "{\n" + - " \"type\": \"LWM2M\",\n" + - " \"observeAttr\": {\n" + - " \"keyName\": {\n" + - " \"/3_1.0/0/9\": \"batteryLevel\"\n" + - " },\n" + - " \"observe\": [],\n" + - " \"attribute\": [\n" + - " ],\n" + - " \"telemetry\": [\n" + - " \"/3_1.0/0/9\"\n" + - " ],\n" + - " \"attributeLwm2m\": {}\n" + - " },\n" + - " \"bootstrap\": {\n" + - " \"servers\": {\n" + - " \"binding\": \"UQ\",\n" + - " \"shortId\": 123,\n" + - " \"lifetime\": 300,\n" + - " \"notifIfDisabled\": true,\n" + - " \"defaultMinPeriod\": 1\n" + - " },\n" + - " \"lwm2mServer\": {\n" + - " \"host\": \"localhost\",\n" + - " \"port\": 5685,\n" + - " \"serverId\": 123,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"serverPublicKey\": \"\",\n" + - " \"bootstrapServerIs\": false,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " },\n" + - " \"bootstrapServer\": {\n" + - " \"host\": \"localhost\",\n" + - " \"port\": 5687,\n" + - " \"serverId\": 111,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"serverPublicKey\": \"\",\n" + - " \"bootstrapServerIs\": true,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " }\n" + - " },\n" + - " \"clientLwM2mSettings\": {\n" + - " \"clientOnlyObserveAfterConnect\": 1\n" + - " }\n" + - "}"; - - private final int port = 5685; - private final Security security = noSec("coap://localhost:" + port, 123); - private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_PORT", Integer.toString(port)); + private final int PORT = 5685; + private final Security SECURITY = noSec("coap://localhost:" + PORT, 123); + private final NetworkConfig COAP_CONFIG = new NetworkConfig().setString("COAP_PORT", Integer.toString(PORT)); + private final String ENDPOINT = "deviceAEndpoint"; @NotNull - private Device createDevice(String deviceAEndpoint) throws Exception { + private Device createDevice() throws Exception { Device device = new Device(); device.setName("Device A"); device.setDeviceProfileId(deviceProfile.getId()); @@ -114,20 +67,18 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { LwM2MCredentials noSecCredentials = new LwM2MCredentials(); NoSecClientCredentials clientCredentials = new NoSecClientCredentials(); - clientCredentials.setEndpoint(deviceAEndpoint); + clientCredentials.setEndpoint(ENDPOINT); noSecCredentials.setClient(clientCredentials); deviceCredentials.setCredentialsValue(JacksonUtil.toString(noSecCredentials)); doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); return device; } -// @Test + @Test public void testConnectAndObserveTelemetry() throws Exception { createDeviceProfile(TRANSPORT_CONFIGURATION); - String deviceAEndpoint = "deviceAEndpoint"; - - Device device = createDevice(deviceAEndpoint); + Device device = createDevice(); SingleEntityFilter sef = new SingleEntityFilter(); sef.setSingleEntity(device.getId()); @@ -144,8 +95,8 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { wsClient.waitForReply(); wsClient.registerWaitForUpdate(); - LwM2MTestClient client = new LwM2MTestClient(executor, deviceAEndpoint); - client.init(security, coapConfig); + LwM2MTestClient client = new LwM2MTestClient(executor, ENDPOINT); + client.init(SECURITY, COAP_CONFIG); String msg = wsClient.waitForUpdate(); EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/X509LwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/X509LwM2MIntegrationTest.java index 18749cfee5..0c13c57441 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/X509LwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/X509LwM2MIntegrationTest.java @@ -47,54 +47,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { - protected final String TRANSPORT_CONFIGURATION = "{\n" + - " \"type\": \"LWM2M\",\n" + - " \"observeAttr\": {\n" + - " \"keyName\": {\n" + - " \"/3_1.0/0/9\": \"batteryLevel\"\n" + - " },\n" + - " \"observe\": [],\n" + - " \"attribute\": [\n" + - " ],\n" + - " \"telemetry\": [\n" + - " \"/3_1.0/0/9\"\n" + - " ],\n" + - " \"attributeLwm2m\": {}\n" + - " },\n" + - " \"bootstrap\": {\n" + - " \"servers\": {\n" + - " \"binding\": \"UQ\",\n" + - " \"shortId\": 123,\n" + - " \"lifetime\": 300,\n" + - " \"notifIfDisabled\": true,\n" + - " \"defaultMinPeriod\": 1\n" + - " },\n" + - " \"lwm2mServer\": {\n" + - " \"host\": \"localhost\",\n" + - " \"port\": 5686,\n" + - " \"serverId\": 123,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"bootstrapServerIs\": false,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " },\n" + - " \"bootstrapServer\": {\n" + - " \"host\": \"localhost\",\n" + - " \"port\": 5687,\n" + - " \"serverId\": 111,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"serverPublicKey\": \"\",\n" + - " \"bootstrapServerIs\": true,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " }\n" + - " },\n" + - " \"clientLwM2mSettings\": {\n" + - " \"clientOnlyObserveAfterConnect\": 1\n" + - " }\n" + - "}"; - - private final int port = 5686; private final NetworkConfig coapConfig = new NetworkConfig().setString("COAP_SECURE_PORT", Integer.toString(port)); private final String endpoint = "deviceAEndpoint"; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 9f7c232203..4ab03fa6c0 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -17,18 +17,11 @@ package org.thingsboard.server.transport.lwm2m.client; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.core.network.CoapEndpoint; import org.eclipse.californium.core.network.config.NetworkConfig; -import org.eclipse.californium.elements.Connector; +import org.eclipse.californium.core.observe.ObservationStore; import org.eclipse.californium.scandium.DTLSConnector; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; -import org.eclipse.californium.scandium.dtls.ClientHandshaker; -import org.eclipse.californium.scandium.dtls.DTLSSession; -import org.eclipse.californium.scandium.dtls.HandshakeException; -import org.eclipse.californium.scandium.dtls.Handshaker; -import org.eclipse.californium.scandium.dtls.ResumingClientHandshaker; -import org.eclipse.californium.scandium.dtls.ResumingServerHandshaker; -import org.eclipse.californium.scandium.dtls.ServerHandshaker; -import org.eclipse.californium.scandium.dtls.SessionAdapter; import org.eclipse.leshan.client.californium.LeshanClient; import org.eclipse.leshan.client.californium.LeshanClientBuilder; import org.eclipse.leshan.client.engine.DefaultRegistrationEngineFactory; @@ -40,7 +33,7 @@ import org.eclipse.leshan.client.resource.ObjectsInitializer; import org.eclipse.leshan.client.servers.ServerIdentity; import org.eclipse.leshan.core.LwM2mId; import org.eclipse.leshan.core.ResponseCode; -import org.eclipse.leshan.core.californium.DefaultEndpointFactory; +import org.eclipse.leshan.core.californium.EndpointFactory; import org.eclipse.leshan.core.model.InvalidDDFFileException; import org.eclipse.leshan.core.model.LwM2mModel; import org.eclipse.leshan.core.model.ObjectLoader; @@ -54,6 +47,7 @@ import org.eclipse.leshan.core.request.RegisterRequest; import org.eclipse.leshan.core.request.UpdateRequest; import java.io.IOException; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledExecutorService; @@ -81,80 +75,49 @@ public class LwM2MTestClient { initializer.setInstancesForObject(SECURITY, security); initializer.setInstancesForObject(SERVER, new Server(123, 300)); initializer.setInstancesForObject(DEVICE, new SimpleLwM2MDevice()); + initializer.setClassForObject(LwM2mId.ACCESS_CONTROL, DummyInstanceEnabler.class); DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); dtlsConfig.setRecommendedCipherSuitesOnly(true); + dtlsConfig.setClientOnly(); DefaultRegistrationEngineFactory engineFactory = new DefaultRegistrationEngineFactory(); engineFactory.setReconnectOnUpdate(false); engineFactory.setResumeOnConnect(true); - DefaultEndpointFactory endpointFactory = new DefaultEndpointFactory(endpoint) { + EndpointFactory endpointFactory = new EndpointFactory() { + + @Override + public CoapEndpoint createUnsecuredEndpoint(InetSocketAddress address, NetworkConfig coapConfig, + ObservationStore store) { + CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); + builder.setInetSocketAddress(address); + builder.setNetworkConfig(coapConfig); + return builder.build(); + } + @Override - protected Connector createSecuredConnector(DtlsConnectorConfig dtlsConfig) { - - return new DTLSConnector(dtlsConfig) { - @Override - protected void onInitializeHandshaker(Handshaker handshaker) { - handshaker.addSessionListener(new SessionAdapter() { - - @Override - public void handshakeStarted(Handshaker handshaker) throws HandshakeException { - if (handshaker instanceof ServerHandshaker) { - log.info("DTLS Full Handshake initiated by server : STARTED ..."); - } else if (handshaker instanceof ResumingServerHandshaker) { - log.info("DTLS abbreviated Handshake initiated by server : STARTED ..."); - } else if (handshaker instanceof ClientHandshaker) { - log.info("DTLS Full Handshake initiated by client : STARTED ..."); - } else if (handshaker instanceof ResumingClientHandshaker) { - log.info("DTLS abbreviated Handshake initiated by client : STARTED ..."); - } - } - - @Override - public void sessionEstablished(Handshaker handshaker, DTLSSession establishedSession) - throws HandshakeException { - if (handshaker instanceof ServerHandshaker) { - log.info("DTLS Full Handshake initiated by server : SUCCEED, handshaker {}", handshaker); - } else if (handshaker instanceof ResumingServerHandshaker) { - log.info("DTLS abbreviated Handshake initiated by server : SUCCEED, handshaker {}", handshaker); - } else if (handshaker instanceof ClientHandshaker) { - log.info("DTLS Full Handshake initiated by client : SUCCEED, handshaker {}", handshaker); - } else if (handshaker instanceof ResumingClientHandshaker) { - log.info("DTLS abbreviated Handshake initiated by client : SUCCEED, handshaker {}", handshaker); - } - } - - @Override - public void handshakeFailed(Handshaker handshaker, Throwable error) { - /** get cause */ - String cause; - if (error != null) { - if (error.getMessage() != null) { - cause = error.getMessage(); - } else { - cause = error.getClass().getName(); - } - } else { - cause = "unknown cause"; - } - - if (handshaker instanceof ServerHandshaker) { - log.info("DTLS Full Handshake initiated by server : FAILED [{}]", cause); - } else if (handshaker instanceof ResumingServerHandshaker) { - log.info("DTLS abbreviated Handshake initiated by server : FAILED [{}]", cause); - } else if (handshaker instanceof ClientHandshaker) { - log.info("DTLS Full Handshake initiated by client : FAILED [{}]", cause); - } else if (handshaker instanceof ResumingClientHandshaker) { - log.info("DTLS abbreviated Handshake initiated by client : FAILED [{}]", cause); - } - } - }); - } - }; + public CoapEndpoint createSecuredEndpoint(DtlsConnectorConfig dtlsConfig, NetworkConfig coapConfig, + ObservationStore store) { + CoapEndpoint.Builder builder = new CoapEndpoint.Builder(); + DtlsConnectorConfig.Builder dtlsConfigBuilder = new DtlsConnectorConfig.Builder(dtlsConfig); + + // tricks to be able to change psk information on the fly +// AdvancedPskStore pskStore = dtlsConfig.getAdvancedPskStore(); +// if (pskStore != null) { +// PskPublicInformation identity = pskStore.getIdentity(null, null); +// SecretKey key = pskStore +// .requestPskSecretResult(ConnectionId.EMPTY, null, identity, null, null, null).getSecret(); +// singlePSKStore = new SinglePSKStore(identity, key); +// dtlsConfigBuilder.setAdvancedPskStore(singlePSKStore); +// } + builder.setConnector(new DTLSConnector(dtlsConfigBuilder.build())); + builder.setNetworkConfig(coapConfig); + return builder.build(); } }; + LeshanClientBuilder builder = new LeshanClientBuilder(endpoint); builder.setLocalAddress("0.0.0.0", 11000); builder.setObjects(initializer.createAll()); diff --git a/application/src/test/resources/lwm2m/credentials/clientKeyStore.jks b/application/src/test/resources/lwm2m/credentials/clientKeyStore.jks index 7cc58589b7..a6c9ae7fae 100644 Binary files a/application/src/test/resources/lwm2m/credentials/clientKeyStore.jks and b/application/src/test/resources/lwm2m/credentials/clientKeyStore.jks differ diff --git a/application/src/test/resources/lwm2m/credentials/serverKeyStore.jks b/application/src/test/resources/lwm2m/credentials/serverKeyStore.jks index f1f03005e1..fc541a3b18 100644 Binary files a/application/src/test/resources/lwm2m/credentials/serverKeyStore.jks and b/application/src/test/resources/lwm2m/credentials/serverKeyStore.jks differ diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java index c57c2295c6..13d6fd6568 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/LwM2mCredentialsSecurityInfoValidator.java @@ -22,16 +22,16 @@ import org.eclipse.leshan.server.security.SecurityInfo; import org.springframework.stereotype.Component; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredentials; +import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredentials; import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; -import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; -import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredentials; -import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredentials; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; @@ -104,9 +104,10 @@ public class LwM2mCredentialsSecurityInfoValidator { result.setEndpoint(endpoint); result.setSecurityMode(credentials.getBootstrap().getBootstrapServer().getSecurityMode()); } else { + result.setEndpoint(credentials.getClient().getEndpoint()); switch (credentials.getClient().getSecurityConfigClientMode()) { case NO_SEC: - createClientSecurityInfoNoSec(result, endpoint); + createClientSecurityInfoNoSec(result); break; case PSK: createClientSecurityInfoPSK(result, endpoint, credentials.getClient()); @@ -125,8 +126,7 @@ public class LwM2mCredentialsSecurityInfoValidator { return result; } - private void createClientSecurityInfoNoSec(TbLwM2MSecurityInfo result, String endpoint) { - result.setEndpoint(endpoint); + private void createClientSecurityInfoNoSec(TbLwM2MSecurityInfo result) { result.setSecurityInfo(null); result.setSecurityMode(NO_SEC); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java index 7b81e733bc..dcd7fa89bb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java @@ -29,22 +29,21 @@ import org.eclipse.californium.scandium.dtls.HandshakeResultHandler; import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier; import org.eclipse.californium.scandium.util.ServerNames; +import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; +import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; import org.thingsboard.server.common.msg.EncryptionUtil; -import org.thingsboard.server.common.transport.TransportService; -import org.thingsboard.server.common.transport.TransportServiceCallback; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.common.transport.util.SslUtil; -import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; -import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; +import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; import javax.annotation.PostConstruct; @@ -57,8 +56,6 @@ import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; @Slf4j @Component @@ -66,9 +63,10 @@ import java.util.concurrent.TimeUnit; @RequiredArgsConstructor public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier { - private final TransportService transportService; private final TbLwM2MDtlsSessionStore sessionStorage; private final LwM2MTransportServerConfig config; + private final LwM2mCredentialsSecurityInfoValidator securityInfoValidator; + private final TbEditableSecurityStore securityStore; @SuppressWarnings("deprecation") private StaticCertificateVerifier staticCertificateVerifier; @@ -119,48 +117,33 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer String strCert = SslUtil.getCertificateString(cert); String sha3Hash = EncryptionUtil.getSha3Hash(strCert); - final ValidateDeviceCredentialsResponse[] deviceCredentialsResponse = new ValidateDeviceCredentialsResponse[1]; - CountDownLatch latch = new CountDownLatch(1); - transportService.process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(sha3Hash).build(), - new TransportServiceCallback<>() { - @Override - public void onSuccess(ValidateDeviceCredentialsResponse msg) { - if (!StringUtils.isEmpty(msg.getCredentials())) { - deviceCredentialsResponse[0] = msg; - } - latch.countDown(); - } - - @Override - public void onError(Throwable e) { - log.error(e.getMessage(), e); - latch.countDown(); - } - }); - if (latch.await(10, TimeUnit.SECONDS)) { - ValidateDeviceCredentialsResponse msg = deviceCredentialsResponse[0]; - if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) { - LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class); - if(!credentials.getClient().getSecurityConfigClientMode().equals(LwM2MSecurityMode.X509)){ - continue; - } - X509ClientCredentials config = (X509ClientCredentials) credentials.getClient(); - String certBody = config.getCert(); - String endpoint = config.getEndpoint(); - if (strCert.equals(certBody)) { - x509CredentialsFound = true; - DeviceProfile deviceProfile = msg.getDeviceProfile(); - if (msg.hasDeviceInfo() && deviceProfile != null) { - sessionStorage.put(endpoint, new TbX509DtlsSessionInfo(cert.getSubjectX500Principal().getName(), msg)); - break; + TbLwM2MSecurityInfo securityInfo = securityInfoValidator.getEndpointSecurityInfoByCredentialsId(sha3Hash, LwM2mTransportUtil.LwM2mTypeServer.CLIENT); + ValidateDeviceCredentialsResponse msg = securityInfo != null ? securityInfo.getMsg() : null; + if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) { + LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class); + if (!credentials.getClient().getSecurityConfigClientMode().equals(LwM2MSecurityMode.X509)) { + continue; + } + X509ClientCredentials config = (X509ClientCredentials) credentials.getClient(); + String certBody = config.getCert(); + String endpoint = config.getEndpoint(); + if (strCert.equals(certBody)) { + x509CredentialsFound = true; + DeviceProfile deviceProfile = msg.getDeviceProfile(); + if (msg.hasDeviceInfo() && deviceProfile != null) { + sessionStorage.put(endpoint, new TbX509DtlsSessionInfo(cert.getSubjectX500Principal().getName(), msg)); + try { + securityStore.put(securityInfo); + } catch (NonUniqueSecurityInfoException e) { + log.trace("Failed to add security info: {}", securityInfo, e); } - } else { - log.trace("[{}][{}] Certificate mismatch. Expected: {}, Actual: {}", endpoint, sha3Hash, strCert, certBody); + break; } + } else { + log.trace("[{}][{}] Certificate mismatch. Expected: {}, Actual: {}", endpoint, sha3Hash, strCert, certBody); } } - } catch (InterruptedException | - CertificateEncodingException | + } catch (CertificateEncodingException | CertificateExpiredException | CertificateNotYetValidException e) { log.error(e.getMessage(), e); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index ac57040d7b..aa204ae868 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.node.LwM2mPath; import org.eclipse.leshan.server.registration.Registration; -import org.eclipse.leshan.server.security.EditableSecurityStore; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; @@ -29,7 +28,6 @@ import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore; -import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore; import java.util.Arrays; import java.util.Collection; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mStoreFactory.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mStoreFactory.java index 3dd9ebd3ed..154de636de 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mStoreFactory.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mStoreFactory.java @@ -17,19 +17,14 @@ package org.thingsboard.server.transport.lwm2m.server.store; import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore; -import org.eclipse.leshan.server.security.EditableSecurityStore; -import org.eclipse.leshan.server.security.InMemorySecurityStore; -import org.eclipse.leshan.server.security.SecurityStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import java.util.Optional; @@ -56,7 +51,7 @@ public class TbLwM2mStoreFactory { } @Bean - private TbSecurityStore securityStore() { + private TbEditableSecurityStore securityStore() { return new TbLwM2mSecurityStore(redisConfiguration.isPresent() && useRedis ? new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new TbInMemorySecurityStore(), validator); }