From 6a370dc6436830fbaf885db83d18066ac24dc4ff Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 26 Jan 2022 17:24:11 +0200 Subject: [PATCH 01/20] lwm2m: tests associated with different security mode (successful): - connection only to lwm2m server - connect bootstrap server, update two client security sections and then connect lwm2m server --- .../controller/AbstractWebsocketTest.java | 2 + .../controller/TbTestWebSocketClient.java | 2 +- .../lwm2m/AbstractLwM2MIntegrationTest.java | 281 ++++++++++++++++-- .../transport/lwm2m/Lwm2mTestHelper.java | 129 ++++++-- .../lwm2m/client/LwM2MTestClient.java | 92 +++++- .../ota/sql/OtaLwM2MIntegrationTest.java | 156 ++++------ .../rpc/AbstractRpcLwM2MIntegrationTest.java | 121 +++----- .../AbstractSecurityLwM2MIntegrationTest.java | 174 ++++++++++- .../sql/NoSecLwM2MIntegrationTest.java | 36 ++- .../security/sql/PskLwm2mIntegrationTest.java | 66 +++- .../security/sql/RpkLwM2MIntegrationTest.java | 72 ++++- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 69 ++++- .../sql/X509_TrustLwM2MIntegrationTest.java | 65 +++- .../resources/application-test.properties | 8 - ...LwM2MBootstrapConfigStoreTaskProvider.java | 14 +- .../lwm2m/server/LwM2MNetworkConfig.java | 12 +- .../server/LwM2mVersionedModelProvider.java | 10 +- 17 files changed, 970 insertions(+), 339 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java index 4760a024c1..2edc985301 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java @@ -22,6 +22,7 @@ import io.jsonwebtoken.Claims; import io.jsonwebtoken.Header; import io.jsonwebtoken.Jwt; import io.jsonwebtoken.Jwts; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.hamcrest.Matcher; @@ -34,6 +35,7 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootContextLoader; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; diff --git a/application/src/test/java/org/thingsboard/server/controller/TbTestWebSocketClient.java b/application/src/test/java/org/thingsboard/server/controller/TbTestWebSocketClient.java index 1b27fb6a62..3abd311aa3 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TbTestWebSocketClient.java +++ b/application/src/test/java/org/thingsboard/server/controller/TbTestWebSocketClient.java @@ -54,7 +54,7 @@ public class TbTestWebSocketClient extends WebSocketClient { @Override public void onClose(int i, String s, boolean b) { - log.error("CLOSED:"); + log.info("CLOSED."); } @Override 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 fd4c748f85..67e17e3d8d 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 @@ -16,6 +16,7 @@ package org.thingsboard.server.transport.lwm2m; import com.fasterxml.jackson.core.type.TypeReference; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; @@ -35,12 +36,22 @@ import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MBootstrapClientCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecBootstrapClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKBootstrapClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKBootstrapClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredential; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; +import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration; +import org.thingsboard.server.common.data.device.profile.lwm2m.TelemetryMappingConfiguration; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.AbstractLwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.NoSecLwM2MBootstrapServerCredential; import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityDataPageLink; import org.thingsboard.server.common.data.query.EntityDataQuery; @@ -58,17 +69,157 @@ 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 java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import static org.awaitility.Awaitility.await; +import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; +import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; +import static org.eclipse.leshan.client.object.Security.noSec; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; +@Slf4j @DaoSqlTest public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { + + // Lwm2m Server + public static final int port = 5685; + public static final int securityPort = 5686; + public static final int portBs = 5687; + public static final int securityPortBs = 5688; + + public static final String host = "localhost"; + public static final String hostBs = "localhost"; + public static final int shortServerId = 123; + public static final int shortServerIdBs = 111; + public static final String COAP = "coap://"; + public static final String COAPS = "coaps://"; + public static final String URI = COAP + host + ":" + port; + public static final String SECURE_URI = COAPS + host + ":" + securityPort; + public static final Configuration COAP_CONFIG = new Configuration().set(COAP_PORT, port).set(COAP_SECURE_PORT, securityPort); + public static final Security SECURITY_NO_SEC = noSec(URI, shortServerId); + + public static final Configuration SECURE_COAP_CONFIG = COAP_CONFIG.set(COAP_SECURE_PORT, securityPort); + public static final Configuration COAP_CONFIG_BS = new Configuration().set(COAP_PORT, portBs); + + + public static final String URI_BS = COAP + hostBs + ":" + portBs; + + public static final String SECURE_URI_BS = COAPS + hostBs + ":" + securityPortBs; + + protected final String OBSERVE_ATTRIBUTES_WITHOUT_PARAMS = + " {\n" + + " \"keyName\": {},\n" + + " \"observe\": [],\n" + + " \"attribute\": [],\n" + + " \"telemetry\": [],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; + + protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS = + + " {\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" + + " }"; + + protected final String CLIENT_LWM2M_SETTINGS = + " {\n" + + " \"edrxCycle\": null,\n" + + " \"powerMode\": \"DRX\",\n" + + " \"fwUpdateResource\": null,\n" + + " \"fwUpdateStrategy\": 1,\n" + + " \"psmActivityTimer\": null,\n" + + " \"swUpdateResource\": null,\n" + + " \"swUpdateStrategy\": 1,\n" + + " \"pagingTransmissionWindow\": null,\n" + + " \"clientOnlyObserveAfterConnect\": 1\n" + + " }"; + + + protected final String TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES = "{\n" + + " \"type\": \"LWM2M\",\n" + + " \"observeAttr\": {\n" + + " \"keyName\": {},\n" + + " \"observe\": [],\n" + + " \"attribute\": [],\n" + + " \"telemetry\": [],\n" + + " \"attributeLwm2m\": {}\n" + + " },\n" + + " \"bootstrapServerUpdateEnable\": true,\n" + + " \"bootstrap\": [\n" + + " {\n" + + " \"host\": \"" + hostBs + "\",\n" + + " \"port\": " + portBs + ",\n" + + " \"binding\": \"U\",\n" + + " \"lifetime\": 300,\n" + + " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + + " \"shortServerId\": " + shortServerIdBs + ",\n" + + " \"notifIfDisabled\": true,\n" + + " \"serverPublicKey\": \"\",\n" + + " \"defaultMinPeriod\": 1,\n" + + " \"bootstrapServerIs\": true,\n" + + " \"clientHoldOffTime\": 1,\n" + + " \"bootstrapServerAccountTimeout\": 0\n" + + " },\n" + + " {\n" + + " \"host\": \"" + host + "\",\n" + + " \"port\": " + port + ",\n" + + " \"binding\": \"U\",\n" + + " \"lifetime\": 300,\n" + + " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + + " \"shortServerId\": " + shortServerId + ",\n" + + " \"notifIfDisabled\": true,\n" + + " \"serverPublicKey\": \"\",\n" + + " \"defaultMinPeriod\": 1,\n" + + " \"bootstrapServerIs\": false,\n" + + " \"clientHoldOffTime\": 1,\n" + + " \"bootstrapServerAccountTimeout\": 0\n" + + " }\n" + + " ],\n" + + " \"clientLwM2mSettings\": {\n" + + " \"edrxCycle\": null,\n" + + " \"powerMode\": \"DRX\",\n" + + " \"fwUpdateResource\": null,\n" + + " \"fwUpdateStrategy\": 1,\n" + + " \"psmActivityTimer\": null,\n" + + " \"swUpdateResource\": null,\n" + + " \"swUpdateStrategy\": 1,\n" + + " \"pagingTransmissionWindow\": null,\n" + + " \"clientOnlyObserveAfterConnect\": 1\n" + + " }\n" + + "}"; + + protected final String TRANSPORT_CONFIGURATION = "{\n" + " \"type\": \"LWM2M\",\n" + " \"observeAttr\": {\n" + @@ -86,12 +237,12 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest " \"bootstrapServerUpdateEnable\": true,\n" + " \"bootstrap\": [\n" + " {\n" + - " \"host\": \"0.0.0.0\",\n" + - " \"port\": 5687,\n" + + " \"host\": \"" + hostBs + "\",\n" + + " \"port\": " + portBs + ",\n" + " \"binding\": \"U\",\n" + " \"lifetime\": 300,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"shortServerId\": 111,\n" + + " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + + " \"shortServerId\": " + shortServerIdBs + ",\n" + " \"notifIfDisabled\": true,\n" + " \"serverPublicKey\": \"\",\n" + " \"defaultMinPeriod\": 1,\n" + @@ -100,12 +251,12 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest " \"bootstrapServerAccountTimeout\": 0\n" + " },\n" + " {\n" + - " \"host\": \"0.0.0.0\",\n" + - " \"port\": 5685,\n" + + " \"host\": \"" + host + "\",\n" + + " \"port\": " + port + ",\n" + " \"binding\": \"U\",\n" + " \"lifetime\": 300,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"shortServerId\": 123,\n" + + " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + + " \"shortServerId\": " + shortServerId + ",\n" + " \"notifIfDisabled\": true,\n" + " \"serverPublicKey\": \"\",\n" + " \"defaultMinPeriod\": 1,\n" + @@ -127,21 +278,20 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest " }\n" + "}"; + protected final Lwm2mDeviceProfileTransportConfiguration LWM2M_TRANSPORT_CONFIGURATION_NO_SEC_WITH_ATTRIBUTES = JacksonUtil.fromString(TRANSPORT_CONFIGURATION, Lwm2mDeviceProfileTransportConfiguration.class); + protected final Lwm2mDeviceProfileTransportConfiguration LWM2M_TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES = JacksonUtil.fromString(TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES, Lwm2mDeviceProfileTransportConfiguration.class); + protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); + protected final Set expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected DeviceProfile deviceProfile; protected ScheduledExecutorService executor; protected TbTestWebSocketClient wsClient; protected LwM2MTestClient client; - private final LwM2MBootstrapClientCredentials defaultBootstrapCredentials; private String[] resources; public AbstractLwM2MIntegrationTest() { - this.defaultBootstrapCredentials = new LwM2MBootstrapClientCredentials(); - NoSecBootstrapClientCredential serverCredentials = new NoSecBootstrapClientCredential(); - this.defaultBootstrapCredentials.setBootstrapServer(serverCredentials); - this.defaultBootstrapCredentials.setLwm2mServer(serverCredentials); } - public void init () throws Exception{ + public void init() throws Exception { executor = Executors.newScheduledThreadPool(10, ThingsBoardThreadFactory.forName("test-lwm2m-scheduled")); loginTenantAdmin(); @@ -167,17 +317,42 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest @After public void after() { - wsClient.close(); clientDestroy(); executor.shutdownNow(); } + public void basicTestConnection(Security security, + LwM2MDeviceCredentials deviceCredentials, + Configuration coapConfig, + String endpoint, + Lwm2mDeviceProfileTransportConfiguration transportConfiguration, + String awaitAlias, Set expectedStatuses, + boolean isBootstrap, LwM2MSecurityMode mode) throws Exception { + createDeviceProfile(transportConfiguration); + createDevice(deviceCredentials, endpoint); + createNewClient(security, coapConfig, false, endpoint, isBootstrap); + + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> ON_REGISTRATION_SUCCESS.equals(client.getClientState())); + Assert.assertEquals(expectedStatuses, client.getClientStates()); + + client.destroy(); + expectedStatuses.add(ON_DEREGISTRATION_STARTED); + expectedStatuses.add(ON_DEREGISTRATION_SUCCESS); + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> ON_DEREGISTRATION_SUCCESS.equals(client.getClientState())); + Assert.assertEquals(expectedStatuses, client.getClientStates()); + } + public void basicTestConnectionObserveTelemetry(Security security, - LwM2MClientCredential credentials, + LwM2MDeviceCredentials deviceCredentials, Configuration coapConfig, String endpoint) throws Exception { - createDeviceProfile(TRANSPORT_CONFIGURATION); - Device device = createDevice(credentials); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE)); + createDeviceProfile(transportConfiguration); + Device device = createDevice(deviceCredentials, endpoint); SingleEntityFilter sef = new SingleEntityFilter(); sef.setSingleEntity(device.getId()); @@ -194,7 +369,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest wsClient.waitForReply(); wsClient.registerWaitForUpdate(); - createNewClient(security, coapConfig, false, endpoint); + createNewClient(security, coapConfig, false, endpoint, false); String msg = wsClient.waitForUpdate(); EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); @@ -208,7 +383,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest Assert.assertEquals(42, Long.parseLong(tsValue.getValue())); } - protected void createDeviceProfile(String transportConfiguration) throws Exception { + protected void createDeviceProfile(Lwm2mDeviceProfileTransportConfiguration transportConfiguration) throws Exception { deviceProfile = new DeviceProfile(); deviceProfile.setName("LwM2M"); deviceProfile.setType(DeviceProfileType.DEFAULT); @@ -220,16 +395,16 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest DeviceProfileData deviceProfileData = new DeviceProfileData(); deviceProfileData.setConfiguration(new DefaultDeviceProfileConfiguration()); deviceProfileData.setProvisionConfiguration(new DisabledDeviceProfileProvisionConfiguration(null)); - deviceProfileData.setTransportConfiguration(JacksonUtil.fromString(transportConfiguration, Lwm2mDeviceProfileTransportConfiguration.class)); + deviceProfileData.setTransportConfiguration(transportConfiguration); deviceProfile.setProfileData(deviceProfileData); deviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class); Assert.assertNotNull(deviceProfile); } - protected Device createDevice(LwM2MClientCredential clientCredentials) throws Exception { + protected Device createDevice(LwM2MDeviceCredentials credentials, String endpoint) throws Exception { Device device = new Device(); - device.setName("Device A"); + device.setName(endpoint); device.setDeviceProfileId(deviceProfile.getId()); device.setTenantId(tenantId); device = doPost("/api/device", device, Device.class); @@ -239,11 +414,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest doGet("/api/device/" + device.getId().getId().toString() + "/credentials", DeviceCredentials.class); Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId()); deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS); - - LwM2MDeviceCredentials credentials = new LwM2MDeviceCredentials(); - credentials.setClient(clientCredentials); - credentials.setBootstrap(defaultBootstrapCredentials); - +// LwM2MDeviceCredentials credentials = getDeviceCredentials(clientCredentials, mode); deviceCredentials.setCredentialsValue(JacksonUtil.toString(credentials)); doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); return device; @@ -259,11 +430,11 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest this.resources = resources; } - public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint) throws Exception { + public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint, boolean isBootstrap) throws Exception { clientDestroy(); client = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableTcpPort(); - client.init(security, coapConfig, clientPort, isRpc); + client.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs); } private void clientDestroy() { @@ -271,4 +442,54 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest client.destroy(); } } + + protected Lwm2mDeviceProfileTransportConfiguration getTransportConfiguration(String observeAttr, List bootstrapServerCredentials) { + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); + TelemetryMappingConfiguration observeAttrConfiguration = JacksonUtil.fromString(observeAttr, TelemetryMappingConfiguration.class); + OtherConfiguration clientLwM2mSettings = JacksonUtil.fromString(CLIENT_LWM2M_SETTINGS, OtherConfiguration.class); + transportConfiguration.setBootstrapServerUpdateEnable(true); + transportConfiguration.setObserveAttr(observeAttrConfiguration); + transportConfiguration.setClientLwM2mSettings(clientLwM2mSettings); + transportConfiguration.setBootstrap(bootstrapServerCredentials); + return transportConfiguration; + } + + protected List getBootstrapServerCredentialsNoSec(LwM2MProfileBootstrapConfigType bootstrapConfigType) { + List bootstrap = new ArrayList<>(); + switch (bootstrapConfigType) { + case BOTH: + bootstrap.add(getBootstrapServerCredentialNoSec(false)); + bootstrap.add(getBootstrapServerCredentialNoSec(true)); + break; + case BOOTSTRAP_ONLY: + bootstrap.add(getBootstrapServerCredentialNoSec(true)); + break; + case LWM2M_ONLY: + bootstrap.add(getBootstrapServerCredentialNoSec(false)); + break; + case NONE: + } + return bootstrap; + } + + private AbstractLwM2MBootstrapServerCredential getBootstrapServerCredentialNoSec(boolean isBootstrap) { + AbstractLwM2MBootstrapServerCredential bootstrapServerCredential = new NoSecLwM2MBootstrapServerCredential(); + bootstrapServerCredential.setServerPublicKey(""); + bootstrapServerCredential.setShortServerId(isBootstrap ? shortServerIdBs : shortServerId); + bootstrapServerCredential.setBootstrapServerIs(isBootstrap); + bootstrapServerCredential.setHost(isBootstrap ? hostBs : host); + bootstrapServerCredential.setPort(isBootstrap ? portBs : port); + return bootstrapServerCredential; + } + + protected LwM2MDeviceCredentials getDeviceCredentialsNoSec(LwM2MClientCredential clientCredentials) { + LwM2MDeviceCredentials credentials = new LwM2MDeviceCredentials(); + credentials.setClient(clientCredentials); + LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); + NoSecBootstrapClientCredential serverCredentials = new NoSecBootstrapClientCredential(); + bootstrapCredentials.setBootstrapServer(serverCredentials); + bootstrapCredentials.setLwm2mServer(serverCredentials); + credentials.setBootstrap(bootstrapCredentials); + return credentials; + } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index 2d10c50bc4..532b1920b2 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -15,29 +15,34 @@ */ package org.thingsboard.server.transport.lwm2m; -import org.eclipse.californium.elements.config.Configuration; -import org.eclipse.leshan.client.object.Security; - -import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; -import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; -import static org.eclipse.leshan.client.object.Security.noSec; - public class Lwm2mTestHelper { - // Server - public static final int SECURE_PORT = 5686; - public static final int SECURE_PORT_BS = 5688; - public static final int PORT = 5685; - public static final int PORT_BS = 5687; - public static final String HOST = "localhost"; - public static final String HOST_BS = "localhost"; - public static final int SHORT_SERVER_ID = 123; - public static final int SHORT_SERVER_ID_BS = 111; - - public static final Configuration SECURE_COAP_CONFIG = new Configuration().set(COAP_SECURE_PORT, SECURE_PORT); - public static final String SECURE_URI = "coaps://" + HOST + ":" + SECURE_PORT; - public static final Security SECURITY = noSec("coap://"+ HOST +":" + PORT, SHORT_SERVER_ID); - public static final Configuration COAP_CONFIG = new Configuration().set(COAP_PORT, PORT); +// // Server +// public static final int SECURE_PORT = 5686; +// public static final int SECURE_PORT_BS = 5688; +// +//// public static final String HOST = "localhost"; +//// public static final int PORT = 5685; +////public static final String URI = "coap://" + HOST + ":" + PORT; +//public static final String SECURE_URI = "coaps://" + HOST + ":" + SECURE_PORT; +// public static final Configuration COAP_CONFIG = new Configuration().set(EXCHANGE_LIFETIME , 200, TimeUnit.SECONDS).set(COAP_PORT, PORT).set(COAP_SECURE_PORT, SECURE_PORT); +// public static final Security SECURITY_NO_SEC = noSec(URI, SHORT_SERVER_ID); +// +// public static final int PORT_BS = 5687; +// +// public static final String HOST_BS = "localhost"; +// public static final int SHORT_SERVER_ID = 123; +// public static final int SHORT_SERVER_ID_BS = 111; +// +// +// public static final Configuration SECURE_COAP_CONFIG = COAP_CONFIG.set(COAP_SECURE_PORT, SECURE_PORT); +// public static final Configuration COAP_CONFIG_BS = new Configuration().set(COAP_PORT, PORT_BS); +// +// +// public static final String URI_BS = "coap://" + HOST_BS + ":" + PORT_BS; +// +// public static final String SECURE_URI_BS = "coaps://" + HOST_BS + ":" + SECURE_PORT_BS; + // Models public static final String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "3.xml", "5.xml", "6.xml", "9.xml", "19.xml", "3303.xml"}; @@ -67,4 +72,86 @@ public class Lwm2mTestHelper { public static final String RESOURCE_ID_NAME_3_14 = "UtfOffset"; public static final String RESOURCE_ID_NAME_19_0_0 = "dataRead"; public static final String RESOURCE_ID_NAME_19_1_0 = "dataWrite"; + + public enum LwM2MClientState { + + ON_INIT(1, "onInit"), + ON_BOOTSTRAP_STARTED(1, "onBootstrapStarted"), + ON_BOOTSTRAP_SUCCESS(2, "onBootstrapSuccess"), + ON_BOOTSTRAP_FAILURE(3, "onBootstrapFailure"), + ON_BOOTSTRAP_TIMEOUT(4, "onBootstrapTimeout"), + ON_REGISTRATION_STARTED(5, "onRegistrationStarted"), + ON_REGISTRATION_SUCCESS(6, "onRegistrationSuccess"), + ON_REGISTRATION_FAILURE(7, "onRegistrationFailure"), + ON_REGISTRATION_TIMEOUT(7, "onRegistrationTimeout"), + ON_UPDATE_STARTED(8, "onUpdateStarted"), + ON_UPDATE_SUCCESS(9, "onUpdateSuccess"), + ON_UPDATE_FAILURE(10, "onUpdateFailure"), + ON_UPDATE_TIMEOUT(11, "onUpdateTimeout"), + ON_DEREGISTRATION_STARTED(12, "onDeregistrationStarted"), + ON_DEREGISTRATION_SUCCESS(13, "onDeregistrationSuccess"), + ON_DEREGISTRATION_FAILURE(14, "onDeregistrationFailure"), + ON_DEREGISTRATION_TIMEOUT(15, "onDeregistrationTimeout"), + ON_EXPECTED_ERROR(16, "onUnexpectedError"); + + public int code; + public String type; + + LwM2MClientState(int code, String type) { + this.code = code; + this.type = type; + } + + public static LwM2MClientState fromLwM2MClientStateByType(String type) { + for (LwM2MClientState to : LwM2MClientState.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported Client State type : %s", type)); + } + + public static LwM2MClientState fromLwM2MClientStateByCode(int code) { + for (LwM2MClientState to : LwM2MClientState.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported Client State code : %s", code)); + } + } + + public enum LwM2MProfileBootstrapConfigType { + + LWM2M_ONLY(1, "only Lwm2m Server"), + BOOTSTRAP_ONLY(2, "only Bootstrap Server"), + BOTH(3, "Lwm2m Server and Bootstrap Server"), + NONE(4, "Without Lwm2m Server and Bootstrap Server"); + + public int code; + public String type; + + LwM2MProfileBootstrapConfigType(int code, String type) { + this.code = code; + this.type = type; + } + + public static LwM2MProfileBootstrapConfigType fromLwM2MBootstrapConfigByType(String type) { + for (LwM2MProfileBootstrapConfigType to : LwM2MProfileBootstrapConfigType.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported Profile Bootstrap Config type : %s", type)); + } + + public static LwM2MProfileBootstrapConfigType fromLwM2MBootstrapConfigByCode(int code) { + for (LwM2MProfileBootstrapConfigType to : LwM2MProfileBootstrapConfigType.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported Profile Bootstrap Config code : %s", code)); + } + } } 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 9180617846..bd3ca6ef9a 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 @@ -45,7 +45,9 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import java.io.IOException; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; @@ -57,6 +59,25 @@ import static org.eclipse.leshan.core.LwM2mId.SECURITY; import static org.eclipse.leshan.core.LwM2mId.SERVER; import static org.eclipse.leshan.core.LwM2mId.SOFTWARE_MANAGEMENT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_FAILURE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_TIMEOUT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_FAILURE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_TIMEOUT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_EXPECTED_ERROR; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_FAILURE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_TIMEOUT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_FAILURE; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_TIMEOUT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_1; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_12; @@ -79,18 +100,23 @@ public class LwM2MTestClient { private LwM2mBinaryAppDataContainer lwM2MBinaryAppDataContainer; private LwM2MLocationParams locationParams; private LwM2mTemperatureSensor lwM2MTemperatureSensor; + private LwM2MClientState clientState; + private Set clientStates; - public void init(Security security, Configuration coapConfig, int port, boolean isRpc) throws InvalidDDFFileException, IOException { + public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, int shortServerId, int shortServerIdBs) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", client); List models = new ArrayList<>(); for (String resourceName : resources) { models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName)); } - LwM2mModel model = new StaticModel(models); ObjectsInitializer initializer = new ObjectsInitializer(model); initializer.setInstancesForObject(SECURITY, security); - initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(123, 300)); + if (isBootstrap) { + initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerIdBs, 300)); + } else { + initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerId, 300)); + } initializer.setInstancesForObject(DEVICE, lwM2MDevice = new SimpleLwM2MDevice()); initializer.setInstancesForObject(FIRMWARE, fwLwM2MDevice = new FwLwM2MDevice()); initializer.setInstancesForObject(SOFTWARE_MANAGEMENT, swLwM2MDevice = new SwLwM2MDevice()); @@ -119,94 +145,128 @@ public class LwM2MTestClient { builder.setDecoder(new DefaultLwM2mDecoder(false)); builder.setEncoder(new DefaultLwM2mEncoder(new LwM2mValueConverterImpl(), false)); + clientState = ON_INIT; + clientStates = new HashSet<>(); + clientStates.add(clientState); client = builder.build(); LwM2mClientObserver observer = new LwM2mClientObserver() { @Override public void onBootstrapStarted(ServerIdentity bsserver, BootstrapRequest request) { - log.info("ClientObserver -> onBootstrapStarted..."); + clientState = ON_BOOTSTRAP_STARTED; + clientStates.add(clientState); +// log.info("ClientObserver -> onBootstrapStarted..."); } @Override public void onBootstrapSuccess(ServerIdentity bsserver, BootstrapRequest request) { - log.info("ClientObserver -> onBootstrapSuccess..."); + clientState = ON_BOOTSTRAP_SUCCESS; + clientStates.add(clientState); +// log.info("ClientObserver -> onBootstrapSuccess..."); } @Override public void onBootstrapFailure(ServerIdentity bsserver, BootstrapRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { - log.info("ClientObserver -> onBootstrapFailure..."); + clientState = ON_BOOTSTRAP_FAILURE; + clientStates.add(clientState); +// log.info("ClientObserver -> onBootstrapFailure..."); } @Override public void onBootstrapTimeout(ServerIdentity bsserver, BootstrapRequest request) { - log.info("ClientObserver -> onBootstrapTimeout..."); + clientState = ON_BOOTSTRAP_TIMEOUT; + clientStates.add(clientState); +// log.info("ClientObserver -> onBootstrapTimeout..."); } @Override public void onRegistrationStarted(ServerIdentity server, RegisterRequest request) { + clientState = ON_REGISTRATION_STARTED; + clientStates.add(clientState); // log.info("ClientObserver -> onRegistrationStarted... EndpointName [{}]", request.getEndpointName()); } @Override public void onRegistrationSuccess(ServerIdentity server, RegisterRequest request, String registrationID) { - log.info("ClientObserver -> onRegistrationSuccess... EndpointName [{}] [{}]", request.getEndpointName(), registrationID); + clientState = ON_REGISTRATION_SUCCESS; + clientStates.add(clientState); +// log.info("ClientObserver -> onRegistrationSuccess... EndpointName [{}] [{}]", request.getEndpointName(), registrationID); } @Override public void onRegistrationFailure(ServerIdentity server, RegisterRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { - log.info("ClientObserver -> onRegistrationFailure... ServerIdentity [{}]", server); + clientState = ON_REGISTRATION_FAILURE; + clientStates.add(clientState); +// log.info("ClientObserver -> onRegistrationFailure... ServerIdentity [{}]", server); } @Override public void onRegistrationTimeout(ServerIdentity server, RegisterRequest request) { - log.info("ClientObserver -> onRegistrationTimeout... RegisterRequest [{}]", request); + clientState = ON_REGISTRATION_TIMEOUT; + clientStates.add(clientState); +// log.info("ClientObserver -> onRegistrationTimeout... RegisterRequest [{}]", request); } @Override public void onUpdateStarted(ServerIdentity server, UpdateRequest request) { + clientState = ON_UPDATE_STARTED; + clientStates.add(clientState); // log.info("ClientObserver -> onUpdateStarted... UpdateRequest [{}]", request); } @Override public void onUpdateSuccess(ServerIdentity server, UpdateRequest request) { + clientState = ON_UPDATE_SUCCESS; + clientStates.add(clientState); // log.info("ClientObserver -> onUpdateSuccess... UpdateRequest [{}]", request); } @Override public void onUpdateFailure(ServerIdentity server, UpdateRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { - + clientState = ON_UPDATE_FAILURE; + clientStates.add(clientState); } @Override public void onUpdateTimeout(ServerIdentity server, UpdateRequest request) { - + clientState = ON_UPDATE_TIMEOUT; + clientStates.add(clientState); } @Override public void onDeregistrationStarted(ServerIdentity server, DeregisterRequest request) { - log.info("ClientObserver ->onDeregistrationStarted... DeregisterRequest [{}]", request.getRegistrationId()); + clientState = ON_DEREGISTRATION_STARTED; + clientStates.add(clientState); +// log.info("ClientObserver ->onDeregistrationStarted... DeregisterRequest [{}]", request.getRegistrationId()); } @Override public void onDeregistrationSuccess(ServerIdentity server, DeregisterRequest request) { + clientState = ON_DEREGISTRATION_SUCCESS; + clientStates.add(clientState); log.info("ClientObserver ->onDeregistrationSuccess... DeregisterRequest [{}]", request.getRegistrationId()); } @Override public void onDeregistrationFailure(ServerIdentity server, DeregisterRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { - log.info("ClientObserver ->onDeregistrationFailure... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); + clientState = ON_DEREGISTRATION_FAILURE; + clientStates.add(clientState); +// log.info("ClientObserver ->onDeregistrationFailure... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); } @Override public void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest request) { - log.info("ClientObserver ->onDeregistrationTimeout... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); + clientState = ON_DEREGISTRATION_TIMEOUT; + clientStates.add(clientState); +// log.info("ClientObserver ->onDeregistrationTimeout... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); } @Override public void onUnexpectedError(Throwable unexpectedError) { - + clientState = ON_EXPECTED_ERROR; + clientStates.add(clientState); } }; this.client.addObserver(observer); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index 3095f28f28..c05e5d6dda 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -20,7 +20,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Test; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus; @@ -46,102 +47,59 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.QUEU import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURITY; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @Slf4j public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { public static final int TIMEOUT = 30; - private final String OTA_TRANSPORT_CONFIGURATION = "{\n" + - " \"type\": \"LWM2M\",\n" + - " \"observeAttr\": {\n" + - " \"keyName\": {\n" + - " \"/5_1.0/0/3\": \"state\",\n" + - " \"/5_1.0/0/5\": \"updateResult\",\n" + - " \"/5_1.0/0/6\": \"pkgname\",\n" + - " \"/5_1.0/0/7\": \"pkgversion\",\n" + - " \"/5_1.0/0/9\": \"firmwareUpdateDeliveryMethod\",\n" + - " \"/9_1.0/0/0\": \"pkgname\",\n" + - " \"/9_1.0/0/1\": \"pkgversion\",\n" + - " \"/9_1.0/0/7\": \"updateState\",\n" + - " \"/9_1.0/0/9\": \"updateResult\"\n" + - " },\n" + - " \"observe\": [\n" + - " \"/5_1.0/0/3\",\n" + - " \"/5_1.0/0/5\",\n" + - " \"/5_1.0/0/6\",\n" + - " \"/5_1.0/0/7\",\n" + - " \"/5_1.0/0/9\",\n" + - " \"/9_1.0/0/0\",\n" + - " \"/9_1.0/0/1\",\n" + - " \"/9_1.0/0/7\",\n" + - " \"/9_1.0/0/9\"\n" + - " ],\n" + - " \"attribute\": [],\n" + - " \"telemetry\": [\n" + - " \"/5_1.0/0/3\",\n" + - " \"/5_1.0/0/5\",\n" + - " \"/5_1.0/0/6\",\n" + - " \"/5_1.0/0/7\",\n" + - " \"/5_1.0/0/9\",\n" + - " \"/9_1.0/0/0\",\n" + - " \"/9_1.0/0/1\",\n" + - " \"/9_1.0/0/7\",\n" + - " \"/9_1.0/0/9\"\n" + - " ],\n" + - " \"attributeLwm2m\": {}\n" + - " },\n" + - " \"bootstrapServerUpdateEnable\": true,\n" + - " \"bootstrap\": [\n" + - " {\n" + - " \"host\": \"0.0.0.0\",\n" + - " \"port\": 5687,\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"shortServerId\": 111,\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": true,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " },\n" + - " {\n" + - " \"host\": \"0.0.0.0\",\n" + - " \"port\": 5685,\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"shortServerId\": 123,\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": false,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " }\n" + - " ],\n" + - " \"clientLwM2mSettings\": {\n" + - " \"edrxCycle\": null,\n" + - " \"powerMode\": \"DRX\",\n" + - " \"fwUpdateResource\": null,\n" + - " \"fwUpdateStrategy\": 1,\n" + - " \"psmActivityTimer\": null,\n" + - " \"swUpdateResource\": null,\n" + - " \"swUpdateStrategy\": 1,\n" + - " \"pagingTransmissionWindow\": null,\n" + - " \"clientOnlyObserveAfterConnect\": 1\n" + - " }\n" + - "}"; - @Test + protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA = + + " {\n" + + " \"keyName\": {\n" + + " \"/5_1.0/0/3\": \"state\",\n" + + " \"/5_1.0/0/5\": \"updateResult\",\n" + + " \"/5_1.0/0/6\": \"pkgname\",\n" + + " \"/5_1.0/0/7\": \"pkgversion\",\n" + + " \"/5_1.0/0/9\": \"firmwareUpdateDeliveryMethod\",\n" + + " \"/9_1.0/0/0\": \"pkgname\",\n" + + " \"/9_1.0/0/1\": \"pkgversion\",\n" + + " \"/9_1.0/0/7\": \"updateState\",\n" + + " \"/9_1.0/0/9\": \"updateResult\"\n" + + " },\n" + + " \"observe\": [\n" + + " \"/5_1.0/0/3\",\n" + + " \"/5_1.0/0/5\",\n" + + " \"/5_1.0/0/6\",\n" + + " \"/5_1.0/0/7\",\n" + + " \"/5_1.0/0/9\",\n" + + " \"/9_1.0/0/0\",\n" + + " \"/9_1.0/0/1\",\n" + + " \"/9_1.0/0/7\",\n" + + " \"/9_1.0/0/9\"\n" + + " ],\n" + + " \"attribute\": [],\n" + + " \"telemetry\": [\n" + + " \"/5_1.0/0/3\",\n" + + " \"/5_1.0/0/5\",\n" + + " \"/5_1.0/0/6\",\n" + + " \"/5_1.0/0/7\",\n" + + " \"/5_1.0/0/9\",\n" + + " \"/9_1.0/0/0\",\n" + + " \"/9_1.0/0/1\",\n" + + " \"/9_1.0/0/7\",\n" + + " \"/9_1.0/0/9\"\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; + @Test public void testFirmwareUpdateWithClientWithoutFirmwareOtaInfoFromProfile() throws Exception { - createDeviceProfile(TRANSPORT_CONFIGURATION); - NoSecClientCredential credentials = createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); - final Device device = createDevice(credentials); - createNewClient(SECURITY, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE)); + createDeviceProfile(transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); + final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, false); Thread.sleep(1000); @@ -163,10 +121,11 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { @Test public void testFirmwareUpdateByObject5() throws Exception { - createDeviceProfile(OTA_TRANSPORT_CONFIGURATION); - NoSecClientCredential credentials = createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5); - final Device device = createDevice(credentials); - createNewClient(SECURITY, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA, getBootstrapServerCredentialsNoSec(NONE)); + createDeviceProfile(transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); + final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, false); Thread.sleep(1000); @@ -200,10 +159,11 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { * */ @Test public void testSoftwareUpdateByObject9() throws Exception { - createDeviceProfile(OTA_TRANSPORT_CONFIGURATION); - NoSecClientCredential credentials = createNoSecClientCredentials(CLIENT_ENDPOINT_OTA9); - final Device device = createDevice(credentials); - createNewClient(SECURITY, COAP_CONFIG, false, CLIENT_ENDPOINT_OTA9); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS_OTA, getBootstrapServerCredentialsNoSec(NONE)); + createDeviceProfile(transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); + final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9, false); Thread.sleep(1000); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 0252c77071..251fccb450 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -17,9 +17,11 @@ package org.thingsboard.server.transport.lwm2m.rpc; import org.junit.Before; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; + import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -31,8 +33,6 @@ import static org.eclipse.leshan.core.LwM2mId.FIRMWARE; import static org.eclipse.leshan.core.LwM2mId.SERVER; import static org.eclipse.leshan.core.LwM2mId.SOFTWARE_MANAGEMENT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURITY; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; @@ -45,12 +45,12 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_14; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.resources; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @DaoSqlTest public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { - protected String RPC_TRANSPORT_CONFIGURATION; - + protected String OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC; protected String deviceId; public Set expectedObjects; public Set expectedObjectIdVers; @@ -71,7 +71,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected static AtomicInteger endpointSequence = new AtomicInteger(); protected static String DEVICE_ENDPOINT_RPC_PREF = "deviceEndpointRpc"; - public AbstractRpcLwM2MIntegrationTest(){ + public AbstractRpcLwM2MIntegrationTest() { setResources(resources); } @@ -79,7 +79,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg public void beforeTest() throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); init(); - createNewClient (SECURITY, COAP_CONFIG, true, endpoint); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, true, endpoint, false); expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); @@ -103,8 +103,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg String ver_Id_0 = client.getClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_0).version; if ("1.0".equals(ver_Id_0)) { objectIdVer_0 = "/" + OBJECT_ID_0; - } - else { + } else { objectIdVer_0 = "/" + OBJECT_ID_0 + "_" + ver_Id_0; } objectIdVer_2 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + ACCESS_CONTROL)).findFirst().get(); @@ -116,86 +115,44 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg objectInstanceIdVer_5 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + FIRMWARE)).findFirst().get(); objectInstanceIdVer_9 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + SOFTWARE_MANAGEMENT)).findFirst().get(); - RPC_TRANSPORT_CONFIGURATION = "{\n" + - " \"type\": \"LWM2M\",\n" + - " \"observeAttr\": {\n" + - " \"keyName\": {\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\": \"" + RESOURCE_ID_NAME_3_14 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_1_0 + "\"\n" + - " },\n" + - " \"observe\": [\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\"\n" + - " ],\n" + - " \"attribute\": [\n" + - " ],\n" + - " \"telemetry\": [\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\"\n" + - " ],\n" + - " \"attributeLwm2m\": {}\n" + - " },\n" + - " \"bootstrapServerUpdateEnable\": true,\n" + - " \"bootstrap\": [\n" + + OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC = " {\n" + - " \"host\": \"0.0.0.0\",\n" + - " \"port\": 5687,\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"shortServerId\": 111,\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": true,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " },\n" + - " {\n" + - " \"host\": \"0.0.0.0\",\n" + - " \"port\": 5685,\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"NO_SEC\",\n" + - " \"shortServerId\": 123,\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": false,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " }\n" + - " ],\n" + - " \"clientLwM2mSettings\": {\n" + - " \"edrxCycle\": null,\n" + - " \"powerMode\": \"DRX\",\n" + - " \"fwUpdateResource\": null,\n" + - " \"fwUpdateStrategy\": 1,\n" + - " \"psmActivityTimer\": null,\n" + - " \"swUpdateResource\": null,\n" + - " \"swUpdateStrategy\": 1,\n" + - " \"pagingTransmissionWindow\": null,\n" + - " \"clientOnlyObserveAfterConnect\": 1\n" + - " }\n" + - "}"; - createDeviceProfile(RPC_TRANSPORT_CONFIGURATION); + " \"keyName\": {\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\": \"" + RESOURCE_ID_NAME_3_14 + "\",\n" + + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" + + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_1_0 + "\"\n" + + " },\n" + + " \"observe\": [\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\"\n" + + " ],\n" + + " \"attribute\": [\n" + + " ],\n" + + " \"telemetry\": [\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\",\n" + + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\",\n" + + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\"\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; + + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC, getBootstrapServerCredentialsNoSec(NONE)); + createDeviceProfile(transportConfiguration); - NoSecClientCredential credentials = createNoSecClientCredentials(endpoint); - final Device device = createDevice(credentials); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(endpoint)); + final Device device = createDevice(deviceCredentials, endpoint); deviceId = device.getId().getId().toString(); client.start(); - } + } protected String pathIdVerToObjectId(String pathIdVer) { - if (pathIdVer.contains("_")){ - String [] objVer = pathIdVer.split("/"); - objVer[1] = objVer[1].split("_")[0]; - return String.join("/", objVer); + if (pathIdVer.contains("_")) { + String[] objVer = pathIdVer.split("/"); + objVer[1] = objVer[1].split("_")[0]; + return String.join("/", objVer); } return pathIdVer; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index c4108a2921..1e22748676 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -15,10 +15,25 @@ */ package org.thingsboard.server.transport.lwm2m.security; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MBootstrapClientCredentials; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecBootstrapClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKBootstrapClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKBootstrapClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.X509BootstrapClientCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.AbstractLwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.PSKLwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.RPKLwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.X509LwM2MBootstrapServerCredential; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; +import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; import java.io.IOException; @@ -27,28 +42,39 @@ import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; @DaoSqlTest +@Slf4j public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest { - protected final String CREDENTIALS_PATH = "lwm2m/credentials/"; // client public key or id used for PSK + protected final String CREDENTIALS_PATH = "lwm2m/credentials/"; // client public key or id used for PSK // Get keys PSK - protected final String CLIENT_PSK_IDENTITY = "SOME_PSK_ID"; // client public key or id used for PSK + protected final String CLIENT_PSK_IDENTITY = "SOME_PSK_ID"; // client public key or id used for PSK + protected final String CLIENT_PSK_IDENTITY_BS = "SOME_PSK_ID_BS"; // client public key or id used for PSK protected final String CLIENT_PSK_KEY = "73656372657450534b73656372657450"; // client private/secret key used for PSK // Server protected static final String SERVER_JKS_FOR_TEST = "lwm2mserver"; protected static final String SERVER_STORE_PWD = "server_ks_password"; protected static final String SERVER_CERT_ALIAS = "server"; -protected final X509Certificate serverX509Cert; // server certificate signed by rootCA - protected final PublicKey serverPublicKeyFromCert; // server public key used for RPK + protected static final String SERVER_CERT_ALIAS_BS = "bootstrap"; + protected final X509Certificate serverX509Cert; // server certificate signed by rootCA + protected final X509Certificate serverX509CertBs; // serverBs certificate signed by rootCA + protected final PublicKey serverPublicKeyFromCert; // server public key used for RPK + protected final PublicKey serverPublicKeyFromCertBs; // serverBs public key used for RPK // Client protected LwM2MTestClient client; protected static final String CLIENT_ENDPOINT_NO_SEC = "LwNoSec00000000"; + protected static final String CLIENT_ENDPOINT_NO_SEC_BS = "LwNoSecBs00000000"; protected static final String CLIENT_ENDPOINT_PSK = "LwPsk00000000"; + protected static final String CLIENT_ENDPOINT_PSK_BS = "LwPskBs00000000"; protected static final String CLIENT_ENDPOINT_RPK = "LwRpk00000000"; + protected static final String CLIENT_ENDPOINT_RPK_BS = "LwRpkBs00000000"; protected static final String CLIENT_ENDPOINT_X509_TRUST = "LwX50900000000"; protected static final String CLIENT_ENDPOINT_X509_TRUST_NO = "LwX509TrustNo"; protected static final String CLIENT_JKS_FOR_TEST = "lwm2mclient"; @@ -56,19 +82,16 @@ protected final X509Certificate serverX509Cert; protected static final String CLIENT_ALIAS_CERT_TRUST = "client_alias_00000000"; protected static final String CLIENT_ALIAS_CERT_TRUST_NO = "client_alias_trust_no"; - protected final X509Certificate clientX509CertTrust; // client certificate signed by intermediate, rootCA with a good CN ("host name") - protected final PrivateKey clientPrivateKeyFromCertTrust; // client private key used for X509 and RPK - protected final PublicKey clientPublicKeyFromCertTrust; // client public key used for RPK - protected final X509Certificate clientX509CertTrustNo; // client certificate signed by intermediate, rootCA with a good CN ("host name") - protected final PrivateKey clientPrivateKeyFromCertTrustNo; // client private key used for X509 and RPK - protected final PublicKey clientPublicKeyFromCertTrustNo; // client public key used for RPK - private final String[] RESOURCES_SECURITY = new String[]{"1.xml", "2.xml", "3.xml", "5.xml", "9.xml"}; + protected final X509Certificate clientX509CertTrust; // client certificate signed by intermediate, rootCA with a good CN ("host name") + protected final PrivateKey clientPrivateKeyFromCertTrust; // client private key used for X509 and RPK + protected final X509Certificate clientX509CertTrustNo; // client certificate signed by intermediate, rootCA with a good CN ("host name") + protected final PrivateKey clientPrivateKeyFromCertTrustNo; // client private key used for X509 and RPK + private final String[] RESOURCES_SECURITY = new String[]{"1.xml", "2.xml", "3.xml", "5.xml", "9.xml"}; private final LwM2MBootstrapClientCredentials defaultBootstrapCredentials; - public AbstractSecurityLwM2MIntegrationTest() { // create client credentials setResources(this.RESOURCES_SECURITY); @@ -82,12 +105,9 @@ protected final X509Certificate serverX509Cert; // Trust clientPrivateKeyFromCertTrust = (PrivateKey) clientKeyStore.getKey(CLIENT_ALIAS_CERT_TRUST, clientKeyStorePwd); clientX509CertTrust = (X509Certificate) clientKeyStore.getCertificate(CLIENT_ALIAS_CERT_TRUST); - clientPublicKeyFromCertTrust = clientX509CertTrust != null ? clientX509CertTrust.getPublicKey() : null; // No trust clientPrivateKeyFromCertTrustNo = (PrivateKey) clientKeyStore.getKey(CLIENT_ALIAS_CERT_TRUST_NO, clientKeyStorePwd); clientX509CertTrustNo = (X509Certificate) clientKeyStore.getCertificate(CLIENT_ALIAS_CERT_TRUST_NO); - clientPublicKeyFromCertTrustNo = clientX509CertTrustNo != null ? clientX509CertTrustNo.getPublicKey() : null; - } catch (GeneralSecurityException | IOException e) { throw new RuntimeException(e); } @@ -103,6 +123,9 @@ protected final X509Certificate serverX509Cert; serverX509Cert = (X509Certificate) serverKeyStore.getCertificate(SERVER_CERT_ALIAS); serverPublicKeyFromCert = serverX509Cert.getPublicKey(); + serverX509CertBs = (X509Certificate) serverKeyStore.getCertificate(SERVER_CERT_ALIAS_BS); + serverPublicKeyFromCertBs = serverX509CertBs.getPublicKey(); + } catch (GeneralSecurityException | IOException e) { throw new RuntimeException(e); } @@ -114,4 +137,125 @@ protected final X509Certificate serverX509Cert; defaultBootstrapCredentials.setBootstrapServer(serverCredentials); defaultBootstrapCredentials.setLwm2mServer(serverCredentials); } + + + protected List getBootstrapServerCredentialsSecure(LwM2MSecurityMode mode, LwM2MProfileBootstrapConfigType bootstrapConfigType) { + List bootstrap = new ArrayList<>(); + switch (bootstrapConfigType) { + case BOTH: + bootstrap.add(getBootstrapServerCredential(mode, false)); + bootstrap.add(getBootstrapServerCredential(mode, true)); + break; + case BOOTSTRAP_ONLY: + bootstrap.add(getBootstrapServerCredential(mode, true)); + break; + case LWM2M_ONLY: + bootstrap.add(getBootstrapServerCredential(mode, false)); + break; + case NONE: + } + return bootstrap; + } + + private AbstractLwM2MBootstrapServerCredential getBootstrapServerCredential(LwM2MSecurityMode mode, boolean isBootstrap) { + AbstractLwM2MBootstrapServerCredential bootstrapServerCredential; + switch (mode) { + case PSK: + bootstrapServerCredential = new PSKLwM2MBootstrapServerCredential(); + bootstrapServerCredential.setServerPublicKey(""); + break; + case RPK: + bootstrapServerCredential = new RPKLwM2MBootstrapServerCredential(); + if (isBootstrap) { + bootstrapServerCredential.setServerPublicKey(Base64.encodeBase64String(serverPublicKeyFromCertBs.getEncoded())); + } else { + bootstrapServerCredential.setServerPublicKey(Base64.encodeBase64String(serverPublicKeyFromCert.getEncoded())); + } + break; + case X509: + bootstrapServerCredential = new X509LwM2MBootstrapServerCredential(); + try { + if (isBootstrap) { + bootstrapServerCredential.setServerPublicKey(Base64.encodeBase64String(serverX509CertBs.getEncoded())); + } else { + bootstrapServerCredential.setServerPublicKey(Base64.encodeBase64String(serverX509Cert.getEncoded())); + } + } catch (CertificateEncodingException e) { + e.printStackTrace(); + } + break; + default: + throw new IllegalStateException("Unexpected value: " + mode); + } + bootstrapServerCredential.setShortServerId(isBootstrap ? shortServerIdBs : shortServerId); + bootstrapServerCredential.setBootstrapServerIs(isBootstrap); + bootstrapServerCredential.setHost(isBootstrap ? hostBs : host); + bootstrapServerCredential.setPort(isBootstrap ? securityPortBs : securityPort); + return bootstrapServerCredential; + } + + + protected LwM2MDeviceCredentials getDeviceCredentialsSecure(LwM2MClientCredential clientCredentials, + PrivateKey privateKey, + X509Certificate certificate, + LwM2MSecurityMode mode) { + LwM2MDeviceCredentials credentials = new LwM2MDeviceCredentials(); + credentials.setClient(clientCredentials); + LwM2MBootstrapClientCredentials bootstrapCredentials; + switch (mode) { + case PSK: + bootstrapCredentials = getBootstrapClientCredentialsPsk(clientCredentials); + break; + case RPK: + bootstrapCredentials = getBootstrapClientCredentialsRpk(certificate, privateKey); + break; + case X509: + bootstrapCredentials = getBootstrapClientCredentialsX509(certificate, privateKey); + break; + default: + throw new IllegalStateException("Unexpected value: " + mode); + } + credentials.setBootstrap(bootstrapCredentials); + return credentials; + } + + private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsPsk(LwM2MClientCredential clientCredentials) { + LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); + PSKBootstrapClientCredential serverCredentials = new PSKBootstrapClientCredential(); + if (clientCredentials != null) { + serverCredentials.setClientSecretKey(((PSKClientCredential) clientCredentials).getKey()); + serverCredentials.setClientPublicKeyOrId(((PSKClientCredential) clientCredentials).getIdentity()); + } + bootstrapCredentials.setBootstrapServer(serverCredentials); + bootstrapCredentials.setLwm2mServer(serverCredentials); + return bootstrapCredentials; + } + + private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsRpk(X509Certificate certificate, PrivateKey privateKey) { + LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); + RPKBootstrapClientCredential serverCredentials = new RPKBootstrapClientCredential(); + if (certificate != null && certificate.getPublicKey() != null && privateKey != null) { + serverCredentials.setClientPublicKeyOrId(Base64.encodeBase64String(certificate.getPublicKey().getEncoded())); + serverCredentials.setClientSecretKey(Base64.encodeBase64String(privateKey.getEncoded())); + } + bootstrapCredentials.setBootstrapServer(serverCredentials); + bootstrapCredentials.setLwm2mServer(serverCredentials); + return bootstrapCredentials; + } + + private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsX509(X509Certificate certificate, PrivateKey privateKey) { + LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); + X509BootstrapClientCredential serverCredentials = new X509BootstrapClientCredential(); + if (certificate != null) { + try { + serverCredentials.setClientPublicKeyOrId(Base64.encodeBase64String(certificate.getEncoded())); + serverCredentials.setClientSecretKey(Base64.encodeBase64String(privateKey.getEncoded())); + } catch (CertificateEncodingException e) { + log.error("Client`s certificate [{}] is bad. [{}]", certificate, e.getMessage()); + } + } + bootstrapCredentials.setBootstrapServer(serverCredentials); + bootstrapCredentials.setLwm2mServer(serverCredentials); + return bootstrapCredentials; + } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java index c324480e17..56874f57aa 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java @@ -15,21 +15,41 @@ */ package org.thingsboard.server.transport.lwm2m.security.sql; -import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.client.object.Security; import org.junit.Test; -import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURITY; +import static org.eclipse.leshan.client.object.Security.noSecBootstap; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; -@Slf4j public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { + //Lwm2m only @Test - public void testConnectAndObserveTelemetry() throws Exception { - NoSecClientCredential clientCredentials = createNoSecClientCredentials(CLIENT_ENDPOINT_NO_SEC); - super.basicTestConnectionObserveTelemetry(SECURITY, clientCredentials, COAP_CONFIG, CLIENT_ENDPOINT_NO_SEC); + public void testWithNoSecConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC; + LwM2MDeviceCredentials clientCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, COAP_CONFIG, clientEndpoint); } + // Bootstrap + Lwm2m + @Test + public void testWithNoSecConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS; + Security securityBs = noSecBootstap(URI_BS); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + this.basicTestConnection(securityBs, + deviceCredentials, + COAP_CONFIG_BS, + clientEndpoint, + transportConfiguration, + "await on client state (NoSecBS two section)", + expectedStatusesRegistrationBsSuccess, + true, + NO_SEC); + } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index f93ab67db9..9afa25c0b3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -18,28 +18,70 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.util.Hex; import org.junit.Test; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; import java.nio.charset.StandardCharsets; import static org.eclipse.leshan.client.object.Security.psk; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_URI; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SHORT_SERVER_ID; +import static org.eclipse.leshan.client.object.Security.pskBootstrap; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { + //Lwm2m only @Test - public void testConnectWithPSKAndObserveTelemetry() throws Exception { + public void testWithPskConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_PSK; + String identity = CLIENT_PSK_IDENTITY; + String keyPsk = CLIENT_PSK_KEY; PSKClientCredential clientCredentials = new PSKClientCredential(); - clientCredentials.setEndpoint(CLIENT_ENDPOINT_PSK); - clientCredentials.setKey(CLIENT_PSK_KEY); - clientCredentials.setIdentity(CLIENT_PSK_IDENTITY); - Security security = psk(SECURE_URI, - SHORT_SERVER_ID, - CLIENT_PSK_IDENTITY.getBytes(StandardCharsets.UTF_8), - Hex.decodeHex(CLIENT_PSK_KEY.toCharArray())); - super.basicTestConnectionObserveTelemetry(security, clientCredentials, SECURE_COAP_CONFIG, CLIENT_ENDPOINT_PSK); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setIdentity(identity); + clientCredentials.setKey(keyPsk); + Security securityBs = psk(SECURE_URI, + shortServerId, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(keyPsk.toCharArray())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); + this.basicTestConnection(securityBs, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (Psk_Lwm2m)", + expectedStatusesRegistrationLwm2mSuccess, + false, + PSK); + } + + // Bootstrap + Lwm2m + @Test + public void testWithPskConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_PSK_BS; + String identity = CLIENT_PSK_IDENTITY_BS; + String keyPsk = CLIENT_PSK_KEY; + PSKClientCredential clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setIdentity(identity); + clientCredentials.setKey(keyPsk); + Security securityBs = pskBootstrap(SECURE_URI_BS, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(keyPsk.toCharArray())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); + this.basicTestConnection(securityBs, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (PskBS two section)", + expectedStatusesRegistrationBsSuccess, + true, + PSK); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index 880d436e69..a28d72117a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -15,30 +15,74 @@ */ package org.thingsboard.server.transport.lwm2m.security.sql; +import org.apache.commons.codec.binary.Base64; import org.eclipse.leshan.client.object.Security; import org.junit.Test; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredential; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import org.apache.commons.codec.binary.Base64;; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; import static org.eclipse.leshan.client.object.Security.rpk; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_URI; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SHORT_SERVER_ID; +import static org.eclipse.leshan.client.object.Security.rpkBootstrap; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.RPK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { + //Lwm2m only @Test - public void testConnectWithRPKAndObserveTelemetry() throws Exception { - RPKClientCredential rpkClientCredentials = new RPKClientCredential(); - rpkClientCredentials.setEndpoint(CLIENT_ENDPOINT_RPK); - rpkClientCredentials.setKey(new String(Base64.encodeBase64(clientPublicKeyFromCertTrust.getEncoded()))); - Security security = rpk(SECURE_URI, - SHORT_SERVER_ID, - clientPublicKeyFromCertTrust.getEncoded(), - clientPrivateKeyFromCertTrust.getEncoded(), - serverPublicKeyFromCert.getEncoded()); - super.basicTestConnectionObserveTelemetry(security, rpkClientCredentials, SECURE_COAP_CONFIG, CLIENT_ENDPOINT_RPK); + public void testWithRpkConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_RPK; + X509Certificate certificate = clientX509CertTrust; + PrivateKey privateKey = clientPrivateKeyFromCertTrust; + RPKClientCredential clientCredentials = new RPKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setKey(Base64.encodeBase64String(certificate.getPublicKey().getEncoded())); + Security securityBs = rpk(SECURE_URI, + shortServerId, + certificate.getPublicKey().getEncoded(), + privateKey.getEncoded(), + serverX509Cert.getPublicKey().getEncoded()); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK); + this.basicTestConnection(securityBs, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (Rpk_Lwm2m)", + expectedStatusesRegistrationLwm2mSuccess, + false, + RPK); + } + + // Bootstrap + Lwm2m + @Test + public void testWithRpkConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_RPK_BS; + X509Certificate certificate = clientX509CertTrust; + PrivateKey privateKey = clientPrivateKeyFromCertTrust; + RPKClientCredential clientCredentials = new RPKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setKey(Base64.encodeBase64String(certificate.getPublicKey().getEncoded())); + Security securityBs = rpkBootstrap(SECURE_URI_BS, + certificate.getPublicKey().getEncoded(), + privateKey.getEncoded(), + serverX509CertBs.getPublicKey().getEncoded()); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK); + this.basicTestConnection(securityBs, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (RpkBS two section)", + expectedStatusesRegistrationBsSuccess, + true, + RPK); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index c7cc24d7ee..1281adc36a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -17,27 +17,72 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import org.eclipse.leshan.client.object.Security; import org.junit.Test; +import org.springframework.util.Base64Utils; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredential; -import org.thingsboard.server.common.transport.util.SslUtil; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + import static org.eclipse.leshan.client.object.Security.x509; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_URI; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SHORT_SERVER_ID; +import static org.eclipse.leshan.client.object.Security.x509Bootstrap; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { + //Lwm2m only @Test - public void testConnectWithCertAndObserveTelemetry() throws Exception { - X509ClientCredential credentials = new X509ClientCredential(); - credentials.setEndpoint(CLIENT_ENDPOINT_X509_TRUST_NO); - credentials.setCert(SslUtil.getCertificateString(clientX509CertTrustNo)); + public void testWithX509NoTrustConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST_NO; + X509Certificate certificate = clientX509CertTrustNo; + PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; + X509ClientCredential clientCredentials = new X509ClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setCert(Base64Utils.encodeToString(certificate.getEncoded())); Security security = x509(SECURE_URI, - SHORT_SERVER_ID, - clientX509CertTrustNo.getEncoded(), - clientPrivateKeyFromCertTrustNo.getEncoded(), + shortServerId, + certificate.getEncoded(), + privateKey.getEncoded(), serverX509Cert.getEncoded()); - super.basicTestConnectionObserveTelemetry(security, credentials, SECURE_COAP_CONFIG, CLIENT_ENDPOINT_X509_TRUST_NO); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + this.basicTestConnection(security, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (X509_Trust_Lwm2m)", + expectedStatusesRegistrationLwm2mSuccess, + false, + X509); + } + + // Bootstrap + Lwm2m + @Test + public void testWithX509NoTrustConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST_NO; + X509Certificate certificate = clientX509CertTrustNo; + PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; + X509ClientCredential clientCredentials = new X509ClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setCert(Base64Utils.encodeToString(certificate.getEncoded())); + Security security = x509Bootstrap(SECURE_URI_BS, + certificate.getEncoded(), + privateKey.getEncoded(), + serverX509CertBs.getEncoded()); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + this.basicTestConnection(security, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (X509NoTrust two section)", + expectedStatusesRegistrationBsSuccess, + true, + X509); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index d59f6ee4ea..40f094a96a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -17,26 +17,71 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import org.eclipse.leshan.client.object.Security; import org.junit.Test; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredential; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + import static org.eclipse.leshan.client.object.Security.x509; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_COAP_CONFIG; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SECURE_URI; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.SHORT_SERVER_ID; +import static org.eclipse.leshan.client.object.Security.x509Bootstrap; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { + //Lwm2m only @Test - public void testConnectAndObserveTelemetry() throws Exception { - X509ClientCredential credentials = new X509ClientCredential(); - credentials.setEndpoint(CLIENT_ENDPOINT_X509_TRUST); + public void testWithX509TrustConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST; + X509Certificate certificate = clientX509CertTrust; + PrivateKey privateKey = clientPrivateKeyFromCertTrust; + X509ClientCredential clientCredentials = new X509ClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setCert(""); Security security = x509(SECURE_URI, - SHORT_SERVER_ID, - clientX509CertTrust.getEncoded(), - clientPrivateKeyFromCertTrust.getEncoded(), + shortServerId, + certificate.getEncoded(), + privateKey.getEncoded(), serverX509Cert.getEncoded()); - super.basicTestConnectionObserveTelemetry(security, credentials, SECURE_COAP_CONFIG, CLIENT_ENDPOINT_X509_TRUST); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + this.basicTestConnection(security, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (X509_Trust_Lwm2m)", + expectedStatusesRegistrationLwm2mSuccess, + false, + X509); } + // Bootstrap + Lwm2m + @Test + public void testWithX509TrustConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST; + X509Certificate certificate = clientX509CertTrust; + PrivateKey privateKey = clientPrivateKeyFromCertTrust; + X509ClientCredential clientCredentials = new X509ClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setCert(""); + Security security = x509Bootstrap(SECURE_URI_BS, + certificate.getEncoded(), + privateKey.getEncoded(), + serverX509CertBs.getEncoded()); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + this.basicTestConnection(security, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + "await on client state (X509Trust two section)", + expectedStatusesRegistrationBsSuccess, + true, + X509); + } } diff --git a/application/src/test/resources/application-test.properties b/application/src/test/resources/application-test.properties index 7f7cb6e8b9..d919319096 100644 --- a/application/src/test/resources/application-test.properties +++ b/application/src/test/resources/application-test.properties @@ -1,20 +1,12 @@ transport.lwm2m.server.security.credentials.enabled=true transport.lwm2m.server.security.credentials.type=KEYSTORE transport.lwm2m.server.security.credentials.keystore.store_file=lwm2m/credentials/lwm2mserver.jks -#transport.lwm2m.server.security.credentials.keystore.store_password=server -#transport.lwm2m.server.security.credentials.keystore.key_alias=server -#transport.lwm2m.server.security.credentials.keystore.key_password=server -transport.lwm2m.bootstrap.enabled=false transport.lwm2m.bootstrap.security.credentials.enabled=true transport.lwm2m.bootstrap.security.credentials.type=KEYSTORE transport.lwm2m.bootstrap.security.credentials.keystore.store_file=lwm2m/credentials/lwm2mserver.jks -#transport.lwm2m.bootstrap.security.credentials.keystore.store_password=server -#transport.lwm2m.bootstrap.security.credentials.keystore.key_alias=server -#transport.lwm2m.bootstrap.security.credentials.keystore.key_password=server transport.lwm2m.security.trust-credentials.enabled=true transport.lwm2m.security.trust-credentials.type=KEYSTORE transport.lwm2m.security.trust-credentials.keystore.store_file=lwm2m/credentials/lwm2mtruststorechain.jks -#transport.lwm2m.security.trust-credentials.keystore.store_password=server edges.enabled=true edges.storage.no_read_records_sleep=500 diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java index 0582ff5450..0bcf65fd70 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java @@ -33,6 +33,8 @@ import org.eclipse.leshan.server.bootstrap.BootstrapSession; import org.eclipse.leshan.server.bootstrap.BootstrapTaskProvider; import org.eclipse.leshan.server.bootstrap.BootstrapUtil; +import java.math.BigInteger; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -43,6 +45,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; +import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; import static org.eclipse.leshan.server.bootstrap.BootstrapUtil.toWriteRequest; @Slf4j @@ -164,9 +167,14 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi protected void findServerInstanceId(BootstrapReadResponse readResponse) { this.serverInstances = new HashMap<>(); - ((LwM2mObject) readResponse.getContent()).getInstances().values().forEach(instance -> { - serverInstances.put(((Long) instance.getResource(0).getValue()).intValue(), instance.getId()); - }); + try { + ((LwM2mObject) readResponse.getContent()).getInstances().values().forEach(instance -> { + Integer shortId = OPAQUE.equals(instance.getResource(0).getType()) ? new BigInteger((byte[]) instance.getResource(0).getValue()).intValue() : (Integer) instance.getResource(0).getValue(); + serverInstances.put(shortId, instance.getId()); + }); + } catch (Exception e) { + log.error("", e); + } if (this.securityInstances != null && this.securityInstances.size() > 0 && this.serverInstances != null && this.serverInstances.size() > 0) { this.findBootstrapServerId(); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java index b47e548b56..f3ab8d2cb8 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java @@ -33,12 +33,12 @@ public class LwM2MNetworkConfig { coapConfig.set(CoapConfig.COAP_SECURE_PORT, serverSecurePort); /** Example:Property for large packet: - #NetworkConfig config = new NetworkConfig(); - #config.setInt(CoapConfig.MAX_MESSAGE_SIZE,32); - #config.setInt(CoapConfig.PREFERRED_BLOCK_SIZE,32); - #config.setInt(CoapConfig.MAX_RESOURCE_BODY_SIZE,2048); - #config.setInt(CoapConfig.MAX_RETRANSMIT,3); - #config.setInt(CoapConfig.MAX_TRANSMIT_WAIT,120000); + #NetworkConfig config = new Configuration(); + #config.sett(CoapConfig.MAX_MESSAGE_SIZE,32); + #config.set(CoapConfig.PREFERRED_BLOCK_SIZE,32); + #config.set(CoapConfig.MAX_RESOURCE_BODY_SIZE,2048); + #config.set(CoapConfig.MAX_RETRANSMIT,3); + #config.set(CoapConfig.MAX_TRANSMIT_WAIT,120000); */ /** diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java index 40514577c3..8f754bc142 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java @@ -85,7 +85,11 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { this.registration = registration; this.tenantId = lwM2mClientContext.getClientByEndpoint(registration.getEndpoint()).getTenantId(); this.modelsLock = new ReentrantLock(); - models.computeIfAbsent(tenantId, t -> new ConcurrentHashMap<>()); + log.info("tenantId: [{}]", tenantId); + log.info("models: [{}]", models); + if (tenantId != null) { + models.computeIfAbsent(tenantId, t -> new ConcurrentHashMap<>()); + } } @Override @@ -127,8 +131,8 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { private ObjectModel getObjectModelDynamic(Integer objectId, String version) { String key = getKeyIdVer(objectId, version); - ObjectModel objectModel = models.get(tenantId).get(key); - if (objectModel == null) { + ObjectModel objectModel = tenantId != null ? models.get(tenantId).get(key) : null; + if (tenantId != null && objectModel == null) { modelsLock.lock(); try { objectModel = models.get(tenantId).get(key); From 3cd9454a980628cefb2a599199e63b22de4d36c6 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 26 Jan 2022 19:05:16 +0200 Subject: [PATCH 02/20] lwm2m: tests with PSK security mode (bad request): - "bad length key" --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 10 +------ .../AbstractSecurityLwM2MIntegrationTest.java | 22 +++++++++++++++ .../security/sql/PskLwm2mIntegrationTest.java | 28 +++++++++++++++++-- .../security/sql/RpkLwM2MIntegrationTest.java | 5 ++-- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 5 ++-- .../sql/X509_TrustLwM2MIntegrationTest.java | 5 ++-- 6 files changed, 58 insertions(+), 17 deletions(-) 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 67e17e3d8d..cd04e8a304 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 @@ -39,10 +39,6 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCr import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecBootstrapClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredential; -import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKBootstrapClientCredential; -import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; -import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKBootstrapClientCredential; -import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredential; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; import org.thingsboard.server.common.data.device.profile.DeviceProfileData; import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration; @@ -95,7 +91,6 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @Slf4j @@ -278,9 +273,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest " }\n" + "}"; - protected final Lwm2mDeviceProfileTransportConfiguration LWM2M_TRANSPORT_CONFIGURATION_NO_SEC_WITH_ATTRIBUTES = JacksonUtil.fromString(TRANSPORT_CONFIGURATION, Lwm2mDeviceProfileTransportConfiguration.class); - protected final Lwm2mDeviceProfileTransportConfiguration LWM2M_TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES = JacksonUtil.fromString(TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES, Lwm2mDeviceProfileTransportConfiguration.class); - protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); + protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected final Set expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected DeviceProfile deviceProfile; protected ScheduledExecutorService executor; @@ -414,7 +407,6 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest doGet("/api/device/" + device.getId().getId().toString() + "/credentials", DeviceCredentials.class); Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId()); deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS); -// LwM2MDeviceCredentials credentials = getDeviceCredentials(clientCredentials, mode); deviceCredentials.setCredentialsValue(JacksonUtil.toString(credentials)); doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); return device; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 1e22748676..8c90fc20bb 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -17,6 +17,10 @@ package org.thingsboard.server.transport.lwm2m.security; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; +import org.junit.Assert; +import org.springframework.test.web.servlet.MvcResult; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MBootstrapClientCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; @@ -31,6 +35,8 @@ import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBo import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.PSKLwM2MBootstrapServerCredential; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.RPKLwM2MBootstrapServerCredential; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.X509LwM2MBootstrapServerCredential; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; @@ -258,4 +264,20 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M bootstrapCredentials.setLwm2mServer(serverCredentials); return bootstrapCredentials; } + + protected MvcResult createDeviceWithMvcResult(LwM2MDeviceCredentials credentials, String endpoint) throws Exception { + Device device = new Device(); + device.setName(endpoint); + device.setDeviceProfileId(deviceProfile.getId()); + device.setTenantId(tenantId); + device = doPost("/api/device", device, Device.class); + Assert.assertNotNull(device); + + DeviceCredentials deviceCredentials = + doGet("/api/device/" + device.getId().getId().toString() + "/credentials", DeviceCredentials.class); + Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId()); + deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS); + deviceCredentials.setCredentialsValue(JacksonUtil.toString(credentials)); + return doPost("/api/device/credentials", deviceCredentials).andReturn(); + } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 9afa25c0b3..19cbab14f3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -18,23 +18,28 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.util.Hex; import org.junit.Test; +import org.springframework.test.web.servlet.MvcResult; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; +import javax.servlet.http.HttpServletResponse; import java.nio.charset.StandardCharsets; import static org.eclipse.leshan.client.object.Security.psk; import static org.eclipse.leshan.client.object.Security.pskBootstrap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { //Lwm2m only @Test - public void testWithPskConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + public void testWithPskConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_PSK; String identity = CLIENT_PSK_IDENTITY; String keyPsk = CLIENT_PSK_KEY; @@ -46,7 +51,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes shortServerId, identity.getBytes(StandardCharsets.UTF_8), Hex.decodeHex(keyPsk.toCharArray())); - Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, BOTH)); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); this.basicTestConnection(securityBs, deviceCredentials, @@ -59,6 +64,25 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes PSK); } + @Test + public void testWithPskConnectLwm2mBadPskKeyByLength_BAD_REQUEST() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_PSK; + String identity = CLIENT_PSK_IDENTITY + "_BadLength"; + String keyPsk = CLIENT_PSK_KEY + "05AC"; + PSKClientCredential clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setIdentity(identity); + clientCredentials.setKey(keyPsk); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); + createDeviceProfile(transportConfiguration); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); + MvcResult result = createDeviceWithMvcResult(deviceCredentials, clientEndpoint); + assertEquals(HttpServletResponse.SC_BAD_REQUEST, result.getResponse().getStatus()); + String msgExpected = "Key must be HexDec format: 32, 64, 128 characters!"; + assertTrue(result.getResponse().getContentAsString().contains(msgExpected)); + } + + // Bootstrap + Lwm2m @Test public void testWithPskConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index a28d72117a..ed2dbfa01f 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -30,12 +30,13 @@ import static org.eclipse.leshan.client.object.Security.rpk; import static org.eclipse.leshan.client.object.Security.rpkBootstrap; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.RPK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { //Lwm2m only @Test - public void testWithRpkConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + public void testWithRpkConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_RPK; X509Certificate certificate = clientX509CertTrust; PrivateKey privateKey = clientPrivateKeyFromCertTrust; @@ -47,7 +48,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes certificate.getPublicKey().getEncoded(), privateKey.getEncoded(), serverX509Cert.getPublicKey().getEncoded()); - Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, BOTH)); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, NONE)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK); this.basicTestConnection(securityBs, deviceCredentials, diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index 1281adc36a..692f1ef7a7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -30,12 +30,13 @@ import static org.eclipse.leshan.client.object.Security.x509; import static org.eclipse.leshan.client.object.Security.x509Bootstrap; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { //Lwm2m only @Test - public void testWithX509NoTrustConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + public void testWithX509NoTrustConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST_NO; X509Certificate certificate = clientX509CertTrustNo; PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; @@ -47,7 +48,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg certificate.getEncoded(), privateKey.getEncoded(), serverX509Cert.getEncoded()); - Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); this.basicTestConnection(security, deviceCredentials, diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index 40f094a96a..04b658ad5e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -29,12 +29,13 @@ import static org.eclipse.leshan.client.object.Security.x509; import static org.eclipse.leshan.client.object.Security.x509Bootstrap; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { //Lwm2m only @Test - public void testWithX509TrustConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + public void testWithX509TrustConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST; X509Certificate certificate = clientX509CertTrust; PrivateKey privateKey = clientPrivateKeyFromCertTrust; @@ -46,7 +47,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra certificate.getEncoded(), privateKey.getEncoded(), serverX509Cert.getEncoded()); - Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); this.basicTestConnection(security, deviceCredentials, From 41274180c567809701845cc1efa305a9966c2b1f Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 27 Jan 2022 14:30:43 +0200 Subject: [PATCH 03/20] lwm2m: tests NoSec bootstrap update: - connecting the client to the bootstrap server and updating the bootstrap - client connection to lwm2m server, reboot when after executing "1/0/9" and update boostrap --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 32 +--- .../transport/lwm2m/Lwm2mTestHelper.java | 1 + .../lwm2m/client/LwM2MTestClient.java | 22 ++- .../ota/sql/OtaLwM2MIntegrationTest.java | 6 +- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 2 +- .../AbstractSecurityLwM2MIntegrationTest.java | 143 +++++++++++++++++- .../sql/NoSecLwM2MIntegrationTest.java | 72 +++++++-- .../security/sql/PskLwm2mIntegrationTest.java | 9 +- .../security/sql/RpkLwM2MIntegrationTest.java | 5 +- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 5 +- .../sql/X509_TrustLwM2MIntegrationTest.java | 5 +- 11 files changed, 238 insertions(+), 64 deletions(-) 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 cd04e8a304..a061eaa187 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 @@ -273,6 +273,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest " }\n" + "}"; + protected final Set expectedStatusesBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS)); protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected final Set expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected DeviceProfile deviceProfile; @@ -314,31 +315,6 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest executor.shutdownNow(); } - public void basicTestConnection(Security security, - LwM2MDeviceCredentials deviceCredentials, - Configuration coapConfig, - String endpoint, - Lwm2mDeviceProfileTransportConfiguration transportConfiguration, - String awaitAlias, Set expectedStatuses, - boolean isBootstrap, LwM2MSecurityMode mode) throws Exception { - createDeviceProfile(transportConfiguration); - createDevice(deviceCredentials, endpoint); - createNewClient(security, coapConfig, false, endpoint, isBootstrap); - - await(awaitAlias) - .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> ON_REGISTRATION_SUCCESS.equals(client.getClientState())); - Assert.assertEquals(expectedStatuses, client.getClientStates()); - - client.destroy(); - expectedStatuses.add(ON_DEREGISTRATION_STARTED); - expectedStatuses.add(ON_DEREGISTRATION_SUCCESS); - await(awaitAlias) - .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> ON_DEREGISTRATION_SUCCESS.equals(client.getClientState())); - Assert.assertEquals(expectedStatuses, client.getClientStates()); - } - public void basicTestConnectionObserveTelemetry(Security security, LwM2MDeviceCredentials deviceCredentials, Configuration coapConfig, @@ -362,7 +338,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest wsClient.waitForReply(); wsClient.registerWaitForUpdate(); - createNewClient(security, coapConfig, false, endpoint, false); + createNewClient(security, coapConfig, false, endpoint, false, null); String msg = wsClient.waitForUpdate(); EntityDataUpdate update = mapper.readValue(msg, EntityDataUpdate.class); @@ -422,11 +398,11 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest this.resources = resources; } - public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint, boolean isBootstrap) throws Exception { + public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint, boolean isBootstrap, Security securityBs) throws Exception { clientDestroy(); client = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableTcpPort(); - client.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs); + client.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); } private void clientDestroy() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index 532b1920b2..b8e3017236 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -51,6 +51,7 @@ public class Lwm2mTestHelper { // Ids in Client public static final int OBJECT_ID_0 = 0; + public static final int OBJECT_ID_1 = 1; public static final int OBJECT_INSTANCE_ID_0 = 0; public static final int OBJECT_INSTANCE_ID_1 = 1; public static final int OBJECT_INSTANCE_ID_2 = 2; 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 bd3ca6ef9a..23c48098f5 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 @@ -26,6 +26,7 @@ import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.client.object.Server; import org.eclipse.leshan.client.observer.LwM2mClientObserver; import org.eclipse.leshan.client.resource.DummyInstanceEnabler; +import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler; import org.eclipse.leshan.client.resource.ObjectsInitializer; import org.eclipse.leshan.client.servers.ServerIdentity; import org.eclipse.leshan.core.ResponseCode; @@ -103,7 +104,7 @@ public class LwM2MTestClient { private LwM2MClientState clientState; private Set clientStates; - public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, int shortServerId, int shortServerIdBs) throws InvalidDDFFileException, IOException { + public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, int shortServerId, int shortServerIdBs, Security securityBs) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", client); List models = new ArrayList<>(); for (String resourceName : resources) { @@ -111,11 +112,24 @@ public class LwM2MTestClient { } LwM2mModel model = new StaticModel(models); ObjectsInitializer initializer = new ObjectsInitializer(model); - initializer.setInstancesForObject(SECURITY, security); + if (securityBs == null) { + initializer.setInstancesForObject(SECURITY, security); + } else { + LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{securityBs, security}; + initializer.setInstancesForObject(SECURITY, instances); + } if (isBootstrap) { initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerIdBs, 300)); } else { - initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerId, 300)); + if (securityBs == null) { + initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerId, 300)); + } else { + Server serverBootstrap = new Server(shortServerIdBs, 300); + Server serverLwm2m = new Server(shortServerId, 300); + LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{serverBootstrap, serverLwm2m}; + initializer.setClassForObject(SERVER, Server.class); + initializer.setInstancesForObject(SERVER, instances); + } } initializer.setInstancesForObject(DEVICE, lwM2MDevice = new SimpleLwM2MDevice()); initializer.setInstancesForObject(FIRMWARE, fwLwM2MDevice = new FwLwM2MDevice()); @@ -245,7 +259,7 @@ public class LwM2MTestClient { public void onDeregistrationSuccess(ServerIdentity server, DeregisterRequest request) { clientState = ON_DEREGISTRATION_SUCCESS; clientStates.add(clientState); - log.info("ClientObserver ->onDeregistrationSuccess... DeregisterRequest [{}]", request.getRegistrationId()); +// log.info("ClientObserver ->onDeregistrationSuccess... DeregisterRequest [{}]", request.getRegistrationId()); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index c05e5d6dda..e572b854b5 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -99,7 +99,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); - createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, false); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, false, null); Thread.sleep(1000); @@ -125,7 +125,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); - createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, false); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, false, null); Thread.sleep(1000); @@ -163,7 +163,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9); - createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9, false); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9, false, null); Thread.sleep(1000); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 251fccb450..1105e94ccd 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -79,7 +79,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg public void beforeTest() throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); init(); - createNewClient(SECURITY_NO_SEC, COAP_CONFIG, true, endpoint, false); + createNewClient(SECURITY_NO_SEC, COAP_CONFIG, true, endpoint, false, null); expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 8c90fc20bb..0de6cd37a1 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -15,8 +15,12 @@ */ package org.thingsboard.server.transport.lwm2m.security; +import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.ResponseCode; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; import org.thingsboard.common.util.JacksonUtil; @@ -30,6 +34,7 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKBootstrapC import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKBootstrapClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.X509BootstrapClientCredential; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.AbstractLwM2MBootstrapServerCredential; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.PSKLwM2MBootstrapServerCredential; @@ -39,8 +44,8 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest; +import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; -import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; import java.io.IOException; import java.io.InputStream; @@ -52,6 +57,20 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.eclipse.leshan.client.object.Security.noSec; +import static org.eclipse.leshan.client.object.Security.noSecBootstap; +import static org.junit.Assert.assertEquals; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_ID_1; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9; @DaoSqlTest @Slf4j @@ -74,7 +93,6 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M protected final PublicKey serverPublicKeyFromCertBs; // serverBs public key used for RPK // Client - protected LwM2MTestClient client; protected static final String CLIENT_ENDPOINT_NO_SEC = "LwNoSec00000000"; protected static final String CLIENT_ENDPOINT_NO_SEC_BS = "LwNoSecBs00000000"; protected static final String CLIENT_ENDPOINT_PSK = "LwPsk00000000"; @@ -144,6 +162,111 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M defaultBootstrapCredentials.setLwm2mServer(serverCredentials); } + public void basicTestConnectionBefore(String clientEndpoint, + String awaitAlias, + LwM2MProfileBootstrapConfigType type, + Set expectedStatuses, + LwM2MClientState finishState) throws Exception { + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + this.basicTestConnection(noSecBootstap(URI_BS), + deviceCredentials, + COAP_CONFIG_BS, + clientEndpoint, + transportConfiguration, + awaitAlias, + expectedStatuses, + true, + finishState); + } + + protected void basicTestConnection(Security security, + LwM2MDeviceCredentials deviceCredentials, + Configuration coapConfig, + String endpoint, + Lwm2mDeviceProfileTransportConfiguration transportConfiguration, + String awaitAlias, + Set expectedStatuses, + boolean isBootstrap, + LwM2MClientState finishState) throws Exception { + createDeviceProfile(transportConfiguration); + createDevice(deviceCredentials, endpoint); + createNewClient(security, coapConfig, false, endpoint, isBootstrap, null); + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> finishState.equals(client.getClientState())); + Assert.assertEquals(expectedStatuses, client.getClientStates()); + + client.destroy(); + if (ON_BOOTSTRAP_SUCCESS != finishState) { + expectedStatuses.add(ON_DEREGISTRATION_STARTED); + expectedStatuses.add(ON_DEREGISTRATION_SUCCESS); + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> ON_DEREGISTRATION_SUCCESS.equals(client.getClientState())); + Assert.assertEquals(expectedStatuses, client.getClientStates()); + } + } + + + + public void basicTestConnectionBootstrapRequestTriggerBefore(String clientEndpoint, String awaitAlias, LwM2MProfileBootstrapConfigType type) throws Exception { + Security securityBs = noSecBootstap(URI_BS); + Security security = noSec(URI, shortServerId); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + this.basicTestConnectionBootstrapRequestTrigger( + security, + deviceCredentials, + COAP_CONFIG_BS, + clientEndpoint, + transportConfiguration, + awaitAlias, + expectedStatusesRegistrationLwm2mSuccess, + expectedStatusesRegistrationBsSuccess, + false, + securityBs); + + } + + private void basicTestConnectionBootstrapRequestTrigger(Security security, + LwM2MDeviceCredentials deviceCredentials, + Configuration coapConfig, + String endpoint, + Lwm2mDeviceProfileTransportConfiguration transportConfiguration, + String awaitAlias, + Set expectedStatusesLwm2m, + Set expectedStatusesBs, + boolean isBootstrap, + Security securityBs) throws Exception { + createDeviceProfile(transportConfiguration); + final Device device = createDevice(deviceCredentials, endpoint); + String deviceId = device.getId().getId().toString(); + createNewClient(security, coapConfig, false, endpoint, isBootstrap, securityBs); + + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> ON_REGISTRATION_SUCCESS.equals(client.getClientState())); + Assert.assertEquals(expectedStatusesLwm2m, client.getClientStates()); + + String executedPath = getObjectIdVer_1() + "/0/" + RESOURCE_ID_9; + String actualResult = sendRPCExecuteById(executedPath, deviceId); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText()); + + expectedStatusesBs.add(ON_DEREGISTRATION_STARTED); + expectedStatusesBs.add(ON_DEREGISTRATION_SUCCESS); + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> ON_REGISTRATION_SUCCESS.equals(client.getClientState())); + Assert.assertEquals(expectedStatusesBs, client.getClientStates()); + + client.destroy(); + await(awaitAlias) + .atMost(1000, TimeUnit.MILLISECONDS) + .until(() -> ON_DEREGISTRATION_SUCCESS.equals(client.getClientState())); + Assert.assertEquals(expectedStatusesBs, client.getClientStates()); + } protected List getBootstrapServerCredentialsSecure(LwM2MSecurityMode mode, LwM2MProfileBootstrapConfigType bootstrapConfigType) { List bootstrap = new ArrayList<>(); @@ -280,4 +403,20 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M deviceCredentials.setCredentialsValue(JacksonUtil.toString(credentials)); return doPost("/api/device/credentials", deviceCredentials).andReturn(); } + + private String sendRPCExecuteById(String path, String deviceId) throws Exception { + String setRpcRequest = "{\"method\": \"Execute\", \"params\": {\"id\": \"" + path + "\"}}"; + return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk()); + } + + private String getObjectIdVer_1() { + String ver_Id_0 = client.getClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version; + String objectIdVer_1; + if ("1.0".equals(ver_Id_0)) { + objectIdVer_1 = "/" + OBJECT_ID_1; + } else { + objectIdVer_1 = "/" + OBJECT_ID_1 + "_" + ver_Id_0; + } + return objectIdVer_1; + } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java index 56874f57aa..345902aa6e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java @@ -15,15 +15,16 @@ */ package org.thingsboard.server.transport.lwm2m.security.sql; -import org.eclipse.leshan.client.object.Security; import org.junit.Test; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; -import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import static org.eclipse.leshan.client.object.Security.noSecBootstap; -import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOOTSTRAP_ONLY; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.LWM2M_ONLY; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { @@ -39,17 +40,56 @@ public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationT @Test public void testWithNoSecConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS; - Security securityBs = noSecBootstap(URI_BS); - Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(BOTH)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); - this.basicTestConnection(securityBs, - deviceCredentials, - COAP_CONFIG_BS, - clientEndpoint, - transportConfiguration, - "await on client state (NoSecBS two section)", - expectedStatusesRegistrationBsSuccess, - true, - NO_SEC); + String awaitAlias = "await on client state (NoSecBS two section)"; + basicTestConnectionBefore(clientEndpoint, awaitAlias, BOTH, expectedStatusesRegistrationBsSuccess, ON_REGISTRATION_SUCCESS); + } + + @Test + public void testWithNoSecConnectBsSuccess_UpdateLwm2mSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + LWM2M_ONLY.name(); + String awaitAlias = "await on client state (NoSecBS Lwm2m section)"; + basicTestConnectionBefore(clientEndpoint, awaitAlias, LWM2M_ONLY, expectedStatusesRegistrationBsSuccess, ON_REGISTRATION_SUCCESS); + } + + @Test + public void testWithNoSecConnectBsSuccess_UpdateBootstrapSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC + BOOTSTRAP_ONLY.name(); + String awaitAlias = "await on client state (NoSecBS Bootstrap section)"; + basicTestConnectionBefore(clientEndpoint, awaitAlias, BOOTSTRAP_ONLY, expectedStatusesBsSuccess, ON_BOOTSTRAP_SUCCESS); + } + + @Test + public void testWithNoSecConnectBsSuccess_UpdateNoneSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC + NONE.name(); + String awaitAlias = "await on client state (NoSecBS None section)"; + basicTestConnectionBefore(clientEndpoint, awaitAlias, NONE, expectedStatusesBsSuccess, ON_BOOTSTRAP_SUCCESS); + } + + @Test + public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateTwoSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOTH.name(); + String awaitAlias = "await on client state (NoSecBS Trigger Two section)"; + basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOTH); + } + + @Test + public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateBootstrapSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOOTSTRAP_ONLY.name(); + String awaitAlias = "await on client state (NoSecBS Trigger Bootstrap section)"; + basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOOTSTRAP_ONLY); + } + + @Test + public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateLwm2mSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + LWM2M_ONLY.name(); + String awaitAlias = "await on client state (NoSecBS Trigger Lwm2m section)"; + basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, LWM2M_ONLY); + } + + @Test + public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateNoneSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + NONE.name(); + String awaitAlias = "await on client state (NoSecBS Trigger None section)"; + basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, NONE); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 19cbab14f3..475771d4c1 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -32,6 +32,7 @@ import static org.eclipse.leshan.client.object.Security.pskBootstrap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @@ -47,13 +48,13 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes clientCredentials.setEndpoint(clientEndpoint); clientCredentials.setIdentity(identity); clientCredentials.setKey(keyPsk); - Security securityBs = psk(SECURE_URI, + Security security = psk(SECURE_URI, shortServerId, identity.getBytes(StandardCharsets.UTF_8), Hex.decodeHex(keyPsk.toCharArray())); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); - this.basicTestConnection(securityBs, + this.basicTestConnection(security, deviceCredentials, COAP_CONFIG, clientEndpoint, @@ -61,7 +62,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (Psk_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - PSK); + ON_REGISTRATION_SUCCESS); } @Test @@ -106,6 +107,6 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (PskBS two section)", expectedStatusesRegistrationBsSuccess, true, - PSK); + ON_REGISTRATION_SUCCESS); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index ed2dbfa01f..ed94443f03 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -29,6 +29,7 @@ import java.security.cert.X509Certificate; import static org.eclipse.leshan.client.object.Security.rpk; import static org.eclipse.leshan.client.object.Security.rpkBootstrap; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.RPK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @@ -58,7 +59,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (Rpk_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - RPK); + ON_REGISTRATION_SUCCESS); } // Bootstrap + Lwm2m @@ -84,6 +85,6 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (RpkBS two section)", expectedStatusesRegistrationBsSuccess, true, - RPK); + ON_REGISTRATION_SUCCESS); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index 692f1ef7a7..b226bc1dad 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -29,6 +29,7 @@ import java.security.cert.X509Certificate; import static org.eclipse.leshan.client.object.Security.x509; import static org.eclipse.leshan.client.object.Security.x509Bootstrap; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @@ -58,7 +59,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg "await on client state (X509_Trust_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - X509); + ON_REGISTRATION_SUCCESS); } // Bootstrap + Lwm2m @@ -84,6 +85,6 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg "await on client state (X509NoTrust two section)", expectedStatusesRegistrationBsSuccess, true, - X509); + ON_REGISTRATION_SUCCESS); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index 04b658ad5e..e5e047ac0f 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -28,6 +28,7 @@ import java.security.cert.X509Certificate; import static org.eclipse.leshan.client.object.Security.x509; import static org.eclipse.leshan.client.object.Security.x509Bootstrap; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @@ -57,7 +58,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra "await on client state (X509_Trust_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - X509); + ON_REGISTRATION_SUCCESS); } // Bootstrap + Lwm2m @@ -83,6 +84,6 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra "await on client state (X509Trust two section)", expectedStatusesRegistrationBsSuccess, true, - X509); + ON_REGISTRATION_SUCCESS); } } From 45a6ce0dbf19a946b247f2aec027dba2de5eed3c Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 27 Jan 2022 16:01:15 +0200 Subject: [PATCH 04/20] lwm2m: tests RPK and X509 client validate base64 format: --- .../lwm2m/client/LwM2MTestClient.java | 16 ------- .../AbstractSecurityLwM2MIntegrationTest.java | 26 +++++++---- .../security/sql/PskLwm2mIntegrationTest.java | 6 +-- .../security/sql/RpkLwM2MIntegrationTest.java | 43 ++++++++++++++++++- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 43 ++++++++++++++++++- .../sql/X509_TrustLwM2MIntegrationTest.java | 4 +- 6 files changed, 105 insertions(+), 33 deletions(-) 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 23c48098f5..e01dc22665 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 @@ -169,70 +169,60 @@ public class LwM2MTestClient { public void onBootstrapStarted(ServerIdentity bsserver, BootstrapRequest request) { clientState = ON_BOOTSTRAP_STARTED; clientStates.add(clientState); -// log.info("ClientObserver -> onBootstrapStarted..."); } @Override public void onBootstrapSuccess(ServerIdentity bsserver, BootstrapRequest request) { clientState = ON_BOOTSTRAP_SUCCESS; clientStates.add(clientState); -// log.info("ClientObserver -> onBootstrapSuccess..."); } @Override public void onBootstrapFailure(ServerIdentity bsserver, BootstrapRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { clientState = ON_BOOTSTRAP_FAILURE; clientStates.add(clientState); -// log.info("ClientObserver -> onBootstrapFailure..."); } @Override public void onBootstrapTimeout(ServerIdentity bsserver, BootstrapRequest request) { clientState = ON_BOOTSTRAP_TIMEOUT; clientStates.add(clientState); -// log.info("ClientObserver -> onBootstrapTimeout..."); } @Override public void onRegistrationStarted(ServerIdentity server, RegisterRequest request) { clientState = ON_REGISTRATION_STARTED; clientStates.add(clientState); -// log.info("ClientObserver -> onRegistrationStarted... EndpointName [{}]", request.getEndpointName()); } @Override public void onRegistrationSuccess(ServerIdentity server, RegisterRequest request, String registrationID) { clientState = ON_REGISTRATION_SUCCESS; clientStates.add(clientState); -// log.info("ClientObserver -> onRegistrationSuccess... EndpointName [{}] [{}]", request.getEndpointName(), registrationID); } @Override public void onRegistrationFailure(ServerIdentity server, RegisterRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { clientState = ON_REGISTRATION_FAILURE; clientStates.add(clientState); -// log.info("ClientObserver -> onRegistrationFailure... ServerIdentity [{}]", server); } @Override public void onRegistrationTimeout(ServerIdentity server, RegisterRequest request) { clientState = ON_REGISTRATION_TIMEOUT; clientStates.add(clientState); -// log.info("ClientObserver -> onRegistrationTimeout... RegisterRequest [{}]", request); } @Override public void onUpdateStarted(ServerIdentity server, UpdateRequest request) { clientState = ON_UPDATE_STARTED; clientStates.add(clientState); -// log.info("ClientObserver -> onUpdateStarted... UpdateRequest [{}]", request); } @Override public void onUpdateSuccess(ServerIdentity server, UpdateRequest request) { clientState = ON_UPDATE_SUCCESS; clientStates.add(clientState); -// log.info("ClientObserver -> onUpdateSuccess... UpdateRequest [{}]", request); } @Override @@ -251,30 +241,24 @@ public class LwM2MTestClient { public void onDeregistrationStarted(ServerIdentity server, DeregisterRequest request) { clientState = ON_DEREGISTRATION_STARTED; clientStates.add(clientState); -// log.info("ClientObserver ->onDeregistrationStarted... DeregisterRequest [{}]", request.getRegistrationId()); - } @Override public void onDeregistrationSuccess(ServerIdentity server, DeregisterRequest request) { clientState = ON_DEREGISTRATION_SUCCESS; clientStates.add(clientState); -// log.info("ClientObserver ->onDeregistrationSuccess... DeregisterRequest [{}]", request.getRegistrationId()); - } @Override public void onDeregistrationFailure(ServerIdentity server, DeregisterRequest request, ResponseCode responseCode, String errorMessage, Exception cause) { clientState = ON_DEREGISTRATION_FAILURE; clientStates.add(clientState); -// log.info("ClientObserver ->onDeregistrationFailure... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); } @Override public void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest request) { clientState = ON_DEREGISTRATION_TIMEOUT; clientStates.add(clientState); -// log.info("ClientObserver ->onDeregistrationTimeout... DeregisterRequest [{}] [{}]", request.getRegistrationId(), request.getRegistrationId()); } @Override diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 0de6cd37a1..a82eb8d86c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -21,6 +21,7 @@ import org.apache.commons.codec.binary.Base64; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.ResponseCode; +import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; import org.thingsboard.common.util.JacksonUtil; @@ -226,7 +227,6 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M expectedStatusesRegistrationBsSuccess, false, securityBs); - } private void basicTestConnectionBootstrapRequestTrigger(Security security, @@ -327,7 +327,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M protected LwM2MDeviceCredentials getDeviceCredentialsSecure(LwM2MClientCredential clientCredentials, PrivateKey privateKey, X509Certificate certificate, - LwM2MSecurityMode mode) { + LwM2MSecurityMode mode, + boolean privateKeyIsBad) { LwM2MDeviceCredentials credentials = new LwM2MDeviceCredentials(); credentials.setClient(clientCredentials); LwM2MBootstrapClientCredentials bootstrapCredentials; @@ -336,10 +337,10 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M bootstrapCredentials = getBootstrapClientCredentialsPsk(clientCredentials); break; case RPK: - bootstrapCredentials = getBootstrapClientCredentialsRpk(certificate, privateKey); + bootstrapCredentials = getBootstrapClientCredentialsRpk(certificate, privateKey, privateKeyIsBad); break; case X509: - bootstrapCredentials = getBootstrapClientCredentialsX509(certificate, privateKey); + bootstrapCredentials = getBootstrapClientCredentialsX509(certificate, privateKey, privateKeyIsBad); break; default: throw new IllegalStateException("Unexpected value: " + mode); @@ -360,25 +361,34 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M return bootstrapCredentials; } - private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsRpk(X509Certificate certificate, PrivateKey privateKey) { + private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsRpk(X509Certificate certificate, PrivateKey privateKey, boolean privateKeyIsBad) { LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); RPKBootstrapClientCredential serverCredentials = new RPKBootstrapClientCredential(); if (certificate != null && certificate.getPublicKey() != null && privateKey != null) { serverCredentials.setClientPublicKeyOrId(Base64.encodeBase64String(certificate.getPublicKey().getEncoded())); - serverCredentials.setClientSecretKey(Base64.encodeBase64String(privateKey.getEncoded())); + if (privateKeyIsBad) { + serverCredentials.setClientSecretKey(Hex.encodeHexString(privateKey.getEncoded())); + } else { + serverCredentials.setClientSecretKey(Base64.encodeBase64String(privateKey.getEncoded())); + + } } bootstrapCredentials.setBootstrapServer(serverCredentials); bootstrapCredentials.setLwm2mServer(serverCredentials); return bootstrapCredentials; } - private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsX509(X509Certificate certificate, PrivateKey privateKey) { + private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsX509(X509Certificate certificate, PrivateKey privateKey, boolean privateKeyIsBad) { LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); X509BootstrapClientCredential serverCredentials = new X509BootstrapClientCredential(); if (certificate != null) { try { serverCredentials.setClientPublicKeyOrId(Base64.encodeBase64String(certificate.getEncoded())); - serverCredentials.setClientSecretKey(Base64.encodeBase64String(privateKey.getEncoded())); + if (privateKeyIsBad) { + serverCredentials.setClientSecretKey(Hex.encodeHexString(privateKey.getEncoded())); + } else { + serverCredentials.setClientSecretKey(Base64.encodeBase64String(privateKey.getEncoded())); + } } catch (CertificateEncodingException e) { log.error("Client`s certificate [{}] is bad. [{}]", certificate, e.getMessage()); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 475771d4c1..9db90a9fdb 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -53,7 +53,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes identity.getBytes(StandardCharsets.UTF_8), Hex.decodeHex(keyPsk.toCharArray())); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); this.basicTestConnection(security, deviceCredentials, COAP_CONFIG, @@ -76,7 +76,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes clientCredentials.setKey(keyPsk); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); createDeviceProfile(transportConfiguration); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); MvcResult result = createDeviceWithMvcResult(deviceCredentials, clientEndpoint); assertEquals(HttpServletResponse.SC_BAD_REQUEST, result.getResponse().getStatus()); String msgExpected = "Key must be HexDec format: 32, 64, 128 characters!"; @@ -98,7 +98,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes identity.getBytes(StandardCharsets.UTF_8), Hex.decodeHex(keyPsk.toCharArray())); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, BOTH)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); this.basicTestConnection(securityBs, deviceCredentials, COAP_CONFIG, diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index ed94443f03..082642690d 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -17,17 +17,22 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import org.apache.commons.codec.binary.Base64; import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.util.Hex; import org.junit.Test; +import org.springframework.test.web.servlet.MvcResult; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredential; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; +import javax.servlet.http.HttpServletResponse; import java.security.PrivateKey; import java.security.cert.X509Certificate; import static org.eclipse.leshan.client.object.Security.rpk; import static org.eclipse.leshan.client.object.Security.rpkBootstrap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.RPK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; @@ -50,7 +55,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes privateKey.getEncoded(), serverX509Cert.getPublicKey().getEncoded()); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, NONE)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK, false); this.basicTestConnection(securityBs, deviceCredentials, COAP_CONFIG, @@ -62,6 +67,40 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes ON_REGISTRATION_SUCCESS); } + @Test + public void testWithRpkValidationPublicKeyBase64format_BAD_REQUEST() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_RPK + "BadPublicKey"; + X509Certificate certificate = clientX509CertTrust; + PrivateKey privateKey = clientPrivateKeyFromCertTrust; + RPKClientCredential clientCredentials = new RPKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setKey(Hex.encodeHexString(certificate.getPublicKey().getEncoded())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, NONE)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK, false); + createDeviceProfile(transportConfiguration); + MvcResult result = createDeviceWithMvcResult(deviceCredentials, clientEndpoint); + assertEquals(HttpServletResponse.SC_BAD_REQUEST, result.getResponse().getStatus()); + String msgExpected = "LwM2M client RPK key must be in standard [RFC7250] and support only EC algorithm and then encoded to Base64 format!"; + assertTrue(result.getResponse().getContentAsString().contains(msgExpected)); + } + + @Test + public void testWithRpkValidationPrivateKeyBase64format_BAD_REQUEST() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_RPK + "BadPrivateKey"; + X509Certificate certificate = clientX509CertTrust; + PrivateKey privateKey = clientPrivateKeyFromCertTrust; + RPKClientCredential clientCredentials = new RPKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setKey(Base64.encodeBase64String(certificate.getPublicKey().getEncoded())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, NONE)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK, true); + createDeviceProfile(transportConfiguration); + MvcResult result = createDeviceWithMvcResult(deviceCredentials, clientEndpoint); + assertEquals(HttpServletResponse.SC_BAD_REQUEST, result.getResponse().getStatus()); + String msgExpected = "Bootstrap server client RPK secret key must be in PKCS#8 format (DER encoding, standard [RFC5958]) and then encoded to Base64 format!"; + assertTrue(result.getResponse().getContentAsString().contains(msgExpected)); + } + // Bootstrap + Lwm2m @Test public void testWithRpkConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { @@ -76,7 +115,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes privateKey.getEncoded(), serverX509CertBs.getPublicKey().getEncoded()); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(RPK, BOTH)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK, false); this.basicTestConnection(securityBs, deviceCredentials, COAP_CONFIG, diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index b226bc1dad..76f5af8965 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -16,18 +16,23 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.util.Hex; import org.junit.Test; +import org.springframework.test.web.servlet.MvcResult; import org.springframework.util.Base64Utils; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredential; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; +import javax.servlet.http.HttpServletResponse; import java.security.PrivateKey; import java.security.cert.X509Certificate; import static org.eclipse.leshan.client.object.Security.x509; import static org.eclipse.leshan.client.object.Security.x509Bootstrap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.X509; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; @@ -50,7 +55,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg privateKey.getEncoded(), serverX509Cert.getEncoded()); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); this.basicTestConnection(security, deviceCredentials, COAP_CONFIG, @@ -62,6 +67,40 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg ON_REGISTRATION_SUCCESS); } + @Test + public void testWithX509NoTrustValidationPublicKeyBase64format_BAD_REQUEST() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST_NO + "BadPublicKey"; + X509Certificate certificate = clientX509CertTrustNo; + PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; + X509ClientCredential clientCredentials = new X509ClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setCert(Hex.encodeHexString(certificate.getEncoded())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); + createDeviceProfile(transportConfiguration); + MvcResult result = createDeviceWithMvcResult(deviceCredentials, clientEndpoint); + assertEquals(HttpServletResponse.SC_BAD_REQUEST, result.getResponse().getStatus()); + String msgExpected = "LwM2M client X509 certificate must be in DER-encoded X509v3 format and support only EC algorithm and then encoded to Base64 format!"; + assertTrue(result.getResponse().getContentAsString().contains(msgExpected)); + } + + @Test + public void testWithX509NoTrustValidationPrivateKeyBase64format_BAD_REQUEST() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_X509_TRUST_NO + "BadPrivateKey"; + X509Certificate certificate = clientX509CertTrustNo; + PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; + X509ClientCredential clientCredentials = new X509ClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setCert(Base64Utils.encodeToString(certificate.getEncoded())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, true); + createDeviceProfile(transportConfiguration); + MvcResult result = createDeviceWithMvcResult(deviceCredentials, clientEndpoint); + assertEquals(HttpServletResponse.SC_BAD_REQUEST, result.getResponse().getStatus()); + String msgExpected = "Bootstrap server client X509 secret key must be in PKCS#8 format (DER encoding, standard [RFC5958]) and then encoded to Base64 format!"; + assertTrue(result.getResponse().getContentAsString().contains(msgExpected)); + } + // Bootstrap + Lwm2m @Test public void testWithX509NoTrustConnectBsSuccess_UpdateTwoSectionsBootstrapAndLm2m_ConnectLwm2mSuccess() throws Exception { @@ -76,7 +115,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg privateKey.getEncoded(), serverX509CertBs.getEncoded()); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); this.basicTestConnection(security, deviceCredentials, COAP_CONFIG, diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index e5e047ac0f..a7087bc072 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -49,7 +49,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra privateKey.getEncoded(), serverX509Cert.getEncoded()); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); this.basicTestConnection(security, deviceCredentials, COAP_CONFIG, @@ -75,7 +75,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra privateKey.getEncoded(), serverX509CertBs.getEncoded()); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, BOTH)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); this.basicTestConnection(security, deviceCredentials, COAP_CONFIG, From c3081c45cf0db6ab63106e790dd77528e06e2241 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 28 Jan 2022 09:50:31 +0200 Subject: [PATCH 05/20] lwm2m: tests with execute "/1/0/9" - add Security and Server with instanceId --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 20 +++--------- .../lwm2m/client/LwM2MTestClient.java | 31 ++++++++++++++----- .../AbstractSecurityLwM2MIntegrationTest.java | 30 +++++++++++------- ...LwM2MBootstrapConfigStoreTaskProvider.java | 11 +++++-- 4 files changed, 54 insertions(+), 38 deletions(-) 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 a061eaa187..510d978046 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 @@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MBootstrapClientCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; -import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecBootstrapClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredential; import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration; @@ -74,19 +73,13 @@ import java.util.List; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import static org.awaitility.Awaitility.await; -import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; -import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; +import static org.eclipse.leshan.client.object.Security.noSecBootstap; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; @@ -112,16 +105,11 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest public static final String COAPS = "coaps://"; public static final String URI = COAP + host + ":" + port; public static final String SECURE_URI = COAPS + host + ":" + securityPort; - public static final Configuration COAP_CONFIG = new Configuration().set(COAP_PORT, port).set(COAP_SECURE_PORT, securityPort); - public static final Security SECURITY_NO_SEC = noSec(URI, shortServerId); - - public static final Configuration SECURE_COAP_CONFIG = COAP_CONFIG.set(COAP_SECURE_PORT, securityPort); - public static final Configuration COAP_CONFIG_BS = new Configuration().set(COAP_PORT, portBs); - - public static final String URI_BS = COAP + hostBs + ":" + portBs; - public static final String SECURE_URI_BS = COAPS + hostBs + ":" + securityPortBs; + public static final Configuration COAP_CONFIG = new Configuration(); + public static final Security SECURITY_NO_SEC = noSec(URI, shortServerId); + public static final Security SECURITY_NO_SEC_BS = noSecBootstap(URI_BS); protected final String OBSERVE_ATTRIBUTES_WITHOUT_PARAMS = " {\n" + 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 e01dc22665..c079513841 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 @@ -94,7 +94,10 @@ public class LwM2MTestClient { private final String endpoint; private LeshanClient client; + private Security lwm2mSecurity; + private Security lwm2mSecurityBs; private Server lwm2mServer; + private Server lwm2mServerBs; private SimpleLwM2MDevice lwM2MDevice; private FwLwM2MDevice fwLwM2MDevice; private SwLwM2MDevice swLwM2MDevice; @@ -113,20 +116,25 @@ public class LwM2MTestClient { LwM2mModel model = new StaticModel(models); ObjectsInitializer initializer = new ObjectsInitializer(model); if (securityBs == null) { - initializer.setInstancesForObject(SECURITY, security); + initializer.setInstancesForObject(SECURITY, this.lwm2mSecurity = security); } else { - LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{securityBs, security}; + securityBs.setId(0); + security.setId(1); + LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{this.lwm2mSecurityBs = securityBs, this.lwm2mSecurity = security}; + initializer.setClassForObject(SECURITY, Security.class); initializer.setInstancesForObject(SECURITY, instances); } if (isBootstrap) { - initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerIdBs, 300)); + initializer.setInstancesForObject(SERVER, lwm2mServerBs = new Server(shortServerIdBs, 300)); } else { if (securityBs == null) { initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerId, 300)); } else { - Server serverBootstrap = new Server(shortServerIdBs, 300); - Server serverLwm2m = new Server(shortServerId, 300); - LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{serverBootstrap, serverLwm2m}; + lwm2mServerBs = new Server(shortServerIdBs, 300); + lwm2mServerBs.setId(0); + lwm2mServer =new Server(shortServerId, 300); + lwm2mServer.setId(1); + LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{lwm2mServerBs, lwm2mServer}; initializer.setClassForObject(SERVER, Server.class); initializer.setInstancesForObject(SERVER, instances); } @@ -277,7 +285,16 @@ public class LwM2MTestClient { if (client != null) { client.destroy(true); } - if (lwm2mServer != null) { + if (lwm2mSecurityBs != null) { + lwm2mSecurityBs = null; + } + if (lwm2mSecurity != null) { + lwm2mSecurity = null; + } + if (lwm2mServerBs != null) { + lwm2mServerBs = null; + } + if (lwm2mServer != null) { lwm2mServer = null; } if (lwM2MDevice != null) { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index a82eb8d86c..05cf0216cc 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -20,7 +20,9 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.CertificateUsage; import org.eclipse.leshan.core.ResponseCode; +import org.eclipse.leshan.core.SecurityMode; import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; @@ -62,7 +64,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; -import static org.eclipse.leshan.client.object.Security.noSec; import static org.eclipse.leshan.client.object.Security.noSecBootstap; import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -172,7 +173,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); this.basicTestConnection(noSecBootstap(URI_BS), deviceCredentials, - COAP_CONFIG_BS, + COAP_CONFIG, clientEndpoint, transportConfiguration, awaitAlias, @@ -190,9 +191,12 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M Set expectedStatuses, boolean isBootstrap, LwM2MClientState finishState) throws Exception { + createNewClient(security, coapConfig, true, endpoint, isBootstrap, null); createDeviceProfile(transportConfiguration); - createDevice(deviceCredentials, endpoint); - createNewClient(security, coapConfig, false, endpoint, isBootstrap, null); + final Device device = createDevice(deviceCredentials, endpoint); + device.getId().getId().toString(); + client.start(); + await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> finishState.equals(client.getClientState())); @@ -212,21 +216,19 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M public void basicTestConnectionBootstrapRequestTriggerBefore(String clientEndpoint, String awaitAlias, LwM2MProfileBootstrapConfigType type) throws Exception { - Security securityBs = noSecBootstap(URI_BS); - Security security = noSec(URI, shortServerId); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); this.basicTestConnectionBootstrapRequestTrigger( - security, + SECURITY_NO_SEC, deviceCredentials, - COAP_CONFIG_BS, + COAP_CONFIG, clientEndpoint, transportConfiguration, awaitAlias, expectedStatusesRegistrationLwm2mSuccess, expectedStatusesRegistrationBsSuccess, false, - securityBs); + SECURITY_NO_SEC_BS); } private void basicTestConnectionBootstrapRequestTrigger(Security security, @@ -239,10 +241,11 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M Set expectedStatusesBs, boolean isBootstrap, Security securityBs) throws Exception { + createNewClient(security, coapConfig, true, endpoint, isBootstrap, securityBs); createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceId = device.getId().getId().toString(); - createNewClient(security, coapConfig, false, endpoint, isBootstrap, securityBs); + client.start(); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) @@ -250,7 +253,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M Assert.assertEquals(expectedStatusesLwm2m, client.getClientStates()); String executedPath = getObjectIdVer_1() + "/0/" + RESOURCE_ID_9; - String actualResult = sendRPCExecuteById(executedPath, deviceId); + String actualResult = sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText()); @@ -414,7 +417,10 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M return doPost("/api/device/credentials", deviceCredentials).andReturn(); } - private String sendRPCExecuteById(String path, String deviceId) throws Exception { + private String sendRPCSecurityExecuteById(String path, String deviceId, String endpoint) throws Exception { + log.info("endpoint1: [{}]", endpoint); + + String setRpcRequest = "{\"method\": \"Execute\", \"params\": {\"id\": \"" + path + "\"}}"; return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk()); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java index 0bcf65fd70..cf4809f11a 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java @@ -34,7 +34,6 @@ import org.eclipse.leshan.server.bootstrap.BootstrapTaskProvider; import org.eclipse.leshan.server.bootstrap.BootstrapUtil; import java.math.BigInteger; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -169,7 +168,13 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi this.serverInstances = new HashMap<>(); try { ((LwM2mObject) readResponse.getContent()).getInstances().values().forEach(instance -> { - Integer shortId = OPAQUE.equals(instance.getResource(0).getType()) ? new BigInteger((byte[]) instance.getResource(0).getValue()).intValue() : (Integer) instance.getResource(0).getValue(); + var shId = OPAQUE.equals(instance.getResource(0).getType()) ? new BigInteger((byte[]) instance.getResource(0).getValue()).intValue() : instance.getResource(0).getValue(); + int shortId; + if (shId instanceof Long) { + shortId = ((Long) shId).intValue(); + } else { + shortId = ((Integer) shId).intValue(); + } serverInstances.put(shortId, instance.getId()); }); } catch (Exception e) { @@ -259,7 +264,7 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi if (this.bootstrapServerIdNew != null && server.getValue().shortId == this.bootstrapServerIdNew && (this.bootstrapServerIdNew != this.bootstrapServerIdOld || securityInstanceId != this.serverInstances.get(this.bootstrapServerIdOld))) { pathsDelete.add("/1/" + this.serverInstances.get(this.bootstrapServerIdOld)); - /** Delete instance if serverIdNew is present in serverInstances and securityInstanceIdOld by serverIdNew not equals serverInstanceIdOld */ + /** Delete instance if serverIdNew is present in serverInstances and securityInstanceIdOld by serverIdNew not equals serverInstanceIdOld */ } else if (this.serverInstances.containsKey(server.getValue().shortId) && securityInstanceId != this.serverInstances.get(server.getValue().shortId)) { pathsDelete.add("/1/" + this.serverInstances.get(server.getValue().shortId)); } From cad54fa70cb4308db19cd36636e6f3eae4718fef Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 28 Jan 2022 12:45:05 +0200 Subject: [PATCH 06/20] lwm2m: fix bug security tests --- .../controller/AbstractWebsocketTest.java | 63 --------- .../lwm2m/AbstractLwM2MIntegrationTest.java | 124 +----------------- .../AbstractSecurityLwM2MIntegrationTest.java | 65 +++++---- .../security/sql/PskLwm2mIntegrationTest.java | 2 +- .../security/sql/RpkLwM2MIntegrationTest.java | 2 +- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 2 +- .../sql/X509_TrustLwM2MIntegrationTest.java | 2 +- 7 files changed, 42 insertions(+), 218 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java index 2edc985301..15884f38a0 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebsocketTest.java @@ -15,83 +15,20 @@ */ package org.thingsboard.server.controller; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jwts; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.hamcrest.Matcher; -import org.junit.After; import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootContextLoader; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.mock.http.MockHttpInputMessage; -import org.springframework.mock.http.MockHttpOutputMessage; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.ResultMatcher; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.context.WebApplicationContext; -import org.thingsboard.server.common.data.BaseData; -import org.thingsboard.server.common.data.Customer; -import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UUIDBased; -import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.common.data.security.Authority; -import org.thingsboard.server.config.ThingsboardSecurityConfiguration; -import org.thingsboard.server.service.mail.TestMailService; -import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest; -import org.thingsboard.server.service.security.auth.rest.LoginRequest; - -import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; @ActiveProfiles("test") @RunWith(SpringRunner.class) 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 510d978046..c63901a7dc 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 @@ -74,10 +74,11 @@ import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; +import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; import static org.eclipse.leshan.client.object.Security.noSecBootstap; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; @@ -107,7 +108,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest public static final String SECURE_URI = COAPS + host + ":" + securityPort; public static final String URI_BS = COAP + hostBs + ":" + portBs; public static final String SECURE_URI_BS = COAPS + hostBs + ":" + securityPortBs; - public static final Configuration COAP_CONFIG = new Configuration(); + public static final Configuration COAP_CONFIG = new Configuration().set(COAP_PORT, port).set(COAP_SECURE_PORT, securityPort); + public static Configuration COAP_CONFIG_BS = new Configuration().set(COAP_PORT, portBs).set(COAP_SECURE_PORT, securityPortBs); public static final Security SECURITY_NO_SEC = noSec(URI, shortServerId); public static final Security SECURITY_NO_SEC_BS = noSecBootstap(URI_BS); @@ -148,121 +150,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest " \"clientOnlyObserveAfterConnect\": 1\n" + " }"; - - protected final String TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES = "{\n" + - " \"type\": \"LWM2M\",\n" + - " \"observeAttr\": {\n" + - " \"keyName\": {},\n" + - " \"observe\": [],\n" + - " \"attribute\": [],\n" + - " \"telemetry\": [],\n" + - " \"attributeLwm2m\": {}\n" + - " },\n" + - " \"bootstrapServerUpdateEnable\": true,\n" + - " \"bootstrap\": [\n" + - " {\n" + - " \"host\": \"" + hostBs + "\",\n" + - " \"port\": " + portBs + ",\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + - " \"shortServerId\": " + shortServerIdBs + ",\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": true,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " },\n" + - " {\n" + - " \"host\": \"" + host + "\",\n" + - " \"port\": " + port + ",\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + - " \"shortServerId\": " + shortServerId + ",\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": false,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " }\n" + - " ],\n" + - " \"clientLwM2mSettings\": {\n" + - " \"edrxCycle\": null,\n" + - " \"powerMode\": \"DRX\",\n" + - " \"fwUpdateResource\": null,\n" + - " \"fwUpdateStrategy\": 1,\n" + - " \"psmActivityTimer\": null,\n" + - " \"swUpdateResource\": null,\n" + - " \"swUpdateStrategy\": 1,\n" + - " \"pagingTransmissionWindow\": null,\n" + - " \"clientOnlyObserveAfterConnect\": 1\n" + - " }\n" + - "}"; - - - 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" + - " \"bootstrapServerUpdateEnable\": true,\n" + - " \"bootstrap\": [\n" + - " {\n" + - " \"host\": \"" + hostBs + "\",\n" + - " \"port\": " + portBs + ",\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + - " \"shortServerId\": " + shortServerIdBs + ",\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": true,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " },\n" + - " {\n" + - " \"host\": \"" + host + "\",\n" + - " \"port\": " + port + ",\n" + - " \"binding\": \"U\",\n" + - " \"lifetime\": 300,\n" + - " \"securityMode\": \"" + NO_SEC.name() + "\",\n" + - " \"shortServerId\": " + shortServerId + ",\n" + - " \"notifIfDisabled\": true,\n" + - " \"serverPublicKey\": \"\",\n" + - " \"defaultMinPeriod\": 1,\n" + - " \"bootstrapServerIs\": false,\n" + - " \"clientHoldOffTime\": 1,\n" + - " \"bootstrapServerAccountTimeout\": 0\n" + - " }\n" + - " ],\n" + - " \"clientLwM2mSettings\": {\n" + - " \"edrxCycle\": null,\n" + - " \"powerMode\": \"DRX\",\n" + - " \"fwUpdateResource\": null,\n" + - " \"fwUpdateStrategy\": 1,\n" + - " \"psmActivityTimer\": null,\n" + - " \"swUpdateResource\": null,\n" + - " \"swUpdateStrategy\": 1,\n" + - " \"pagingTransmissionWindow\": null,\n" + - " \"clientOnlyObserveAfterConnect\": 1\n" + - " }\n" + - "}"; - - protected final Set expectedStatusesBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS)); - protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); + protected final Set expectedStatusesBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS)); + protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected final Set expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected DeviceProfile deviceProfile; protected ScheduledExecutorService executor; @@ -299,6 +188,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest @After public void after() { + wsClient.close(); clientDestroy(); executor.shutdownNow(); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 05cf0216cc..2f1d528573 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -20,9 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; -import org.eclipse.leshan.core.CertificateUsage; import org.eclipse.leshan.core.ResponseCode; -import org.eclipse.leshan.core.SecurityMode; import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; @@ -173,7 +171,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); this.basicTestConnection(noSecBootstap(URI_BS), deviceCredentials, - COAP_CONFIG, + COAP_CONFIG_BS, clientEndpoint, transportConfiguration, awaitAlias, @@ -183,14 +181,14 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M } protected void basicTestConnection(Security security, - LwM2MDeviceCredentials deviceCredentials, - Configuration coapConfig, - String endpoint, - Lwm2mDeviceProfileTransportConfiguration transportConfiguration, - String awaitAlias, - Set expectedStatuses, - boolean isBootstrap, - LwM2MClientState finishState) throws Exception { + LwM2MDeviceCredentials deviceCredentials, + Configuration coapConfig, + String endpoint, + Lwm2mDeviceProfileTransportConfiguration transportConfiguration, + String awaitAlias, + Set expectedStatuses, + boolean isBootstrap, + LwM2MClientState finishState) throws Exception { createNewClient(security, coapConfig, true, endpoint, isBootstrap, null); createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); @@ -214,33 +212,32 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M } - public void basicTestConnectionBootstrapRequestTriggerBefore(String clientEndpoint, String awaitAlias, LwM2MProfileBootstrapConfigType type) throws Exception { - Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type)); - LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); - this.basicTestConnectionBootstrapRequestTrigger( - SECURITY_NO_SEC, - deviceCredentials, - COAP_CONFIG, - clientEndpoint, - transportConfiguration, - awaitAlias, - expectedStatusesRegistrationLwm2mSuccess, - expectedStatusesRegistrationBsSuccess, - false, - SECURITY_NO_SEC_BS); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + this.basicTestConnectionBootstrapRequestTrigger( + SECURITY_NO_SEC, + deviceCredentials, + COAP_CONFIG, + clientEndpoint, + transportConfiguration, + awaitAlias, + expectedStatusesRegistrationLwm2mSuccess, + expectedStatusesRegistrationBsSuccess, + false, + SECURITY_NO_SEC_BS); } private void basicTestConnectionBootstrapRequestTrigger(Security security, - LwM2MDeviceCredentials deviceCredentials, - Configuration coapConfig, - String endpoint, - Lwm2mDeviceProfileTransportConfiguration transportConfiguration, - String awaitAlias, - Set expectedStatusesLwm2m, - Set expectedStatusesBs, - boolean isBootstrap, - Security securityBs) throws Exception { + LwM2MDeviceCredentials deviceCredentials, + Configuration coapConfig, + String endpoint, + Lwm2mDeviceProfileTransportConfiguration transportConfiguration, + String awaitAlias, + Set expectedStatusesLwm2m, + Set expectedStatusesBs, + boolean isBootstrap, + Security securityBs) throws Exception { createNewClient(security, coapConfig, true, endpoint, isBootstrap, securityBs); createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 9db90a9fdb..feff1ee926 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -101,7 +101,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); this.basicTestConnection(securityBs, deviceCredentials, - COAP_CONFIG, + COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (PskBS two section)", diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index 082642690d..cfc55fae9a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -118,7 +118,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK, false); this.basicTestConnection(securityBs, deviceCredentials, - COAP_CONFIG, + COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (RpkBS two section)", diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index 76f5af8965..6e9dc615e5 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -118,7 +118,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); this.basicTestConnection(security, deviceCredentials, - COAP_CONFIG, + COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (X509NoTrust two section)", diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index a7087bc072..59c7360d20 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -78,7 +78,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); this.basicTestConnection(security, deviceCredentials, - COAP_CONFIG, + COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (X509Trust two section)", From 1f2eaf07edb14d63ec3597c09f00e2f587559161 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Sun, 30 Jan 2022 22:21:00 +0200 Subject: [PATCH 07/20] lwm2m: del shell from tests --- .../lwm2m/lwm2m_cfssl_chain_all_for_test.sh | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/tools/src/main/shell/lwm2m/lwm2m_cfssl_chain_all_for_test.sh b/tools/src/main/shell/lwm2m/lwm2m_cfssl_chain_all_for_test.sh index de7538bc36..5856d07932 100755 --- a/tools/src/main/shell/lwm2m/lwm2m_cfssl_chain_all_for_test.sh +++ b/tools/src/main/shell/lwm2m/lwm2m_cfssl_chain_all_for_test.sh @@ -29,26 +29,41 @@ cd -- "$( dirname "${0}" )" || exit 1 -Help() +ResultInfo() { - # Display Help - echo "Description of the script functions." - echo - echo "Syntax: scriptTemplate [-g|h|v|V]" - echo "options:" - echo "h Print this Help." - echo "v Verbose mode." - echo "V Print software version and exit." - echo +# # Display Help +# echo "Description of the script functions." +# echo +# echo "Syntax: scriptTemplate [-g|h|v|V]" +# echo "options:" +# echo "h Print this Help." +# echo "v Verbose mode." +# echo "V Print software version and exit." +# echo +if [ "$IS_IHFO" = false ] ; then + if [ "$IS_SERVER_CREATED_KEY" = true ] ; then + ./lwm2m_cfssl_chain_server_for_test.sh > /dev/null 2>&1 & + fi + if [ "$IS_TRUST_CLIENT_CREATED_KEY" = true ] ; then + ./lwM2M_cfssl_chain_clients_for_test.sh ${INTERMEDIATE_START} ${INTERMEDIATE_FINISH} ${CLIENT_START} ${CLIENT_FINISH} > /dev/null 2>&1 & + fi +else + if [ "$IS_SERVER_CREATED_KEY" = true ] ; then + ./lwm2m_cfssl_chain_server_for_test.sh + fi + if [ "$IS_TRUST_CLIENT_CREATED_KEY" = true ] ; then + ./lwM2M_cfssl_chain_clients_for_test.sh ${INTERMEDIATE_START} ${INTERMEDIATE_FINISH} ${CLIENT_START} ${CLIENT_FINISH} + fi +fi } -if [ "$1" == "-h" ] ; then - echo -e "Usage 1: ./`basename $0` \"Information is not displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are generated\"" - echo -e "Usage 2: ./`basename $0` true \"Information is displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are generated\"" - echo -e "Usage 3: ./`basename $0` true false \"Information is displayed\" : \"Keys for the server are not generated\" : \"Keys for the clients and trusts are generated\"" - echo -e "Usage 4: ./`basename $0` true false false \"Information is displayed\" : \"Keys for the server are not generated\" : \"Keys for the clients and trusts are not generated\"" - echo -e "Usage 5: ./`basename $0` true true false \"Information is displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are not generated\"" - echo "This Help File: ./`basename $0` -h" +if [ "$1" == "-h" ] ||[ "$1" == "-?" ] || [ "$1" == "-help" ] ; then + echo -e "Usage 1: \"Information is not displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are generated\"\n./`basename $0`" + echo -e "Usage 2: \"Information is displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are generated\"\n./`basename $0` true \n./`basename $0` true true true " + echo -e "Usage 3: \"Information is displayed\" : \"Keys for the server are not generated\" : \"Keys for the clients and trusts are generated\"\n./`basename $0` true false \n./`basename $0` true false true" + echo -e "Usage 4: \"Information is displayed\" : \"Keys for the server are not generated\" : \"Keys for the clients and trusts are not generated\"\n./`basename $0` true false false" + echo -e "Usage 5: \"Information is displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are not generated\"\n./`basename $0` true true false" + echo -e "This Help File: \n./`basename $0` -h | -? | -help" exit 0 fi @@ -64,6 +79,14 @@ if [ -n "$3" ]; then IS_TRUST_CLIENT_CREATED_KEY=$3 fi +if [ "$IS_SERVER_CREATED_KEY" = false ] && [ "$IS_TRUST_CLIENT_CREATED_KEY" = false ] ; then + echo -e "Result is null" + echo -e "This Help File: \n./`basename $0` -h | -? | -help" + exit 0 +fi + + + if [ "$IS_IHFO" = false ] ; then if [ "$IS_SERVER_CREATED_KEY" = true ] ; then ./lwm2m_cfssl_chain_server_for_test.sh > /dev/null 2>&1 & @@ -78,4 +101,15 @@ else if [ "$IS_TRUST_CLIENT_CREATED_KEY" = true ] ; then ./lwM2M_cfssl_chain_clients_for_test.sh ${INTERMEDIATE_START} ${INTERMEDIATE_FINISH} ${CLIENT_START} ${CLIENT_FINISH} fi -fi \ No newline at end of file +fi + +echo -e "Result into:" +if [ "$IS_SERVER_CREATED_KEY" = true ] ; then + echo -e "./Server" +fi +if [ "$IS_TRUST_CLIENT_CREATED_KEY" = true ] ; then + echo -e "./Client" + echo -e "./Trust" +fi + +echo -e "Finish" \ No newline at end of file From 11140fe89ba5283d9a76723f8afa0f58d9d612ac Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Sun, 30 Jan 2022 22:24:29 +0200 Subject: [PATCH 08/20] lwm2m: del shell from tests --- ...cfssl_chain_trusts_and_clients_for_test.sh | 299 ------------------ .../shell/lwm2m_cfssl_chain_for_test_All.sh | 65 ---- .../lwm2m_cfssl_chain_server_for_test.sh | 298 ----------------- 3 files changed, 662 deletions(-) delete mode 100755 application/src/test/resources/lwm2m/credentials/shell/lwM2M_cfssl_chain_trusts_and_clients_for_test.sh delete mode 100755 application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_for_test_All.sh delete mode 100755 application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_server_for_test.sh diff --git a/application/src/test/resources/lwm2m/credentials/shell/lwM2M_cfssl_chain_trusts_and_clients_for_test.sh b/application/src/test/resources/lwm2m/credentials/shell/lwM2M_cfssl_chain_trusts_and_clients_for_test.sh deleted file mode 100755 index 26f47266a7..0000000000 --- a/application/src/test/resources/lwm2m/credentials/shell/lwM2M_cfssl_chain_trusts_and_clients_for_test.sh +++ /dev/null @@ -1,299 +0,0 @@ -#!/usr/bin/env bash - -# Change working directory -cd -- "$( - dirname "${0}" -)" || exit 1 - -readonly TRUST_PATH="Trust" -readonly CA_ROOT_CERT_KEY="ca-root" -readonly CA_ROOT_ALIAS="root" -readonly CA_INTERMEDIATE_CERT_KEY_PREF="intermediate_ca" -CA_INTERMEDIATE_START=0 -CA_INTERMEDIATE_FINISH=2 -CA_INTERMEDIATE_NUMBER=${CA_INTERMEDIATE_START} -CA_INTERMEDIATE_CERT_SIGN=${CA_ROOT_CERT_KEY} -CA_LIST_CERT_FOR_CAT="" -readonly CA_TRUST_STORE_ALL_CHAIN="lwm2mtruststorechain" -readonly CA_TRUST_STORE_PWD="server_ks_password" -readonly CA_TRUST_CERT_ALIAS="root" -readonly CA_TRUST_CERT_CHAIN_JKS="lwm2mtruststorechain" -readonly CA_TRUST_STORE_CHAIN_ALIAS="trust_cert_chain_alias" - -readonly CLIENT_PATH="Client" -readonly CLIENT_JKS_FOR_TEST="lwm2mclient" -readonly CLIENT_CERT_KEY_PREF="LwX509" -readonly CLIENT_CERT_ALIAS_PREF="client_alias_" -readonly CLIENT_STORE_PWD="client_ks_password" -readonly CLIENT_HOST_NAME="thingsboard_test.io" -CLIENT_START=0 -CLIENT_FINISH=1 -CLIENT_NUMBER=${CLIENT_START} - -SERVER_HOST_NAME="localhost.localdomain" -SERVER_LOCAL_HOST_NAME="localhost" -SERVER_PUBLIC_HOST_NAMES="-" - -readonly CF_COMMANDS=" - cfssl - cfssljson -" - -if [ ! -z "$1" ]; then - CA_INTERMEDIATE_START=$1 - CA_INTERMEDIATE_NUMBER=${CA_INTERMEDIATE_START} -fi - -if [ ! -z "$2" ]; then - CA_INTERMEDIATE_FINISH=$2 -fi - -if [ ! -z "$3" ]; then - CLIENT_START=$1 - CLIENT_NUMBER=${CLIENT_START} -fi - -if [ ! -z "$4" ]; then - CLIENT_FINISH=$4 -fi - -# Change working directory -rm -rf ${TRUST_PATH} -mkdir -p ${TRUST_PATH} -rm -rf ${CLIENT_PATH} -mkdir -p ${CLIENT_PATH} -cd -- "$( - dirname "${0}" -)" || exit 1 - - -rm *.csr -rm *.p12 -rm *.json -rm *.pem -rm *.jks - -intermediate_common_name() { - echo "${CA_INTERMEDIATE_CERT_KEY_PREF}${CA_INTERMEDIATE_NUMBER}" -} - -set_list_sert_for_cat() { - local first="$1" - echo "$first ${CA_LIST_CERT_FOR_CAT}" -} - -client_common_name() { - echo "${CLIENT_CERT_KEY_PREF}$(printf "%08d" ${CLIENT_NUMBER})" -} - -client_alias_name() { - echo "${CLIENT_CERT_ALIAS_PREF}$(printf "%08d" ${CLIENT_NUMBER})" -} - -for COMMAND in ${CF_COMMANDS}; do - if ! command -v ${COMMAND} &> /dev/null; then - echo "ERROR: Missing command ${COMMAND}" >&2 - echo "Install the package from: https://pkg.cfssl.org/" >&2 - exit 1 - fi -done - -tee ./${TRUST_PATH}/ca-config.json 1> /dev/null <<-CONFIG -{ - "signing": { - "default": { - "expiry": "8760h", - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ] - }, - "profiles": { - "server": { - "expiry": "43800h", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "signing", - "key encipherment", - "server auth" - ] - }, - "client": { - "expiry": "43800h", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "signing", - "key encipherment", - "client auth" - ] - }, - "client-server": { - "expiry": "43800h", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "signing", - "key encipherment", - "server auth", - "client auth" - ] - } - } - } -} -CONFIG - -tee ./${TRUST_PATH}/ca-root-to-intermediate-config.json 1> /dev/null <<-CONFIG -{ - "signing": { - "default": { - "expiry": "43800h", - "ca_constraint": { - "is_ca": true, - "max_path_len": 0, - "max_path_len_zero": true - }, - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "digital signature", - "cert sign", - "crl sign", - "signing" - ] - } - } -} -CONFIG - -echo "====================================================" -echo -e "Generate the root of certificates: \n-${CA_ROOT_KEY}-key.pem (certificate key)\n-${CA_ROOT_KEY}.pem (certificate)\n-${CA_ROOT_KEY}.csr (sign request)" -echo "====================================================" -cfssl genkey \ - -initca \ - - \ - <<-CONFIG | cfssljson -bare ./${TRUST_PATH}/${CA_ROOT_CERT_KEY} -{ - "CN": "ROOT CA", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ], - "ca": { - "expiry": "131400h" - } -} -CONFIG -CA_LIST_CERT_FOR_CAT=$(set_list_sert_for_cat ./${TRUST_PATH}/${CA_ROOT_CERT_KEY}.pem) - -echo "====================================================" -echo -e "Generate and Signed the intermediates of our certificates: \n-${CA_INTERMEDIATE_CERT_KEY_PREF}?-key.pem (certificate key)\n-${CA_INTERMEDIATE_CERT_KEY_PREF}?.pem (certificate)\n-${CA_INTERMEDIATE_CERT_KEY_PREF}?.csr (sign request)" -echo "====================================================" - -while [[ ${CA_INTERMEDIATE_NUMBER} -lt ${CA_INTERMEDIATE_FINISH} ]]; -do - CA_INTERMEDIATE_CERT_KEY=$(intermediate_common_name) - CA_INTERMEDIATE_NUMBER=$((${CA_INTERMEDIATE_NUMBER} + 1)) - - cfssl gencert \ - -ca ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_SIGN}.pem \ - -ca-key ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_SIGN}-key.pem \ - -config ./${TRUST_PATH}/ca-root-to-intermediate-config.json \ - -hostname "${SERVER_HOST_NAME},${SERVER_LOCAL_HOST_NAME}${SERVER_PUBLIC_HOST_NAMES:+, }${SERVER_PUBLIC_HOST_NAMES}" \ - - \ - <<-CONFIG | cfssljson -bare ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY} - { - "CN": "${CA_INTERMEDIATE_CERT_KEY}", - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ] - } -CONFIG - #openssl x509 -in ${CA_INTERMEDIATE_CERT_KEY}.pem -text -noout - CA_LIST_CERT_FOR_CAT=$(set_list_sert_for_cat ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem) - CA_INTERMEDIATE_CERT_SIGN=${CA_INTERMEDIATE_CERT_KEY} -done - -echo "====================================================" -echo -e "Add the CA_certificate to keystore: ${CA_TRUST_CERT_CHAIN_JKS}.jks" -echo "====================================================" -cat ${CA_LIST_CERT_FOR_CAT} > ./${TRUST_PATH}/${CA_TRUST_STORE_ALL_CHAIN}.pem -openssl pkcs12 -export -in ./${TRUST_PATH}/${CA_TRUST_STORE_ALL_CHAIN}.pem -inkey ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}-key.pem -out ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}.p12 -name ${CA_TRUST_STORE_CHAIN_ALIAS} -CAfile ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem -caname ${CA_ROOT_ALIAS} -passin pass:${CA_TRUST_STORE_PWD} -passout pass:${CA_TRUST_STORE_PWD} -keytool -importkeystore -deststorepass ${CA_TRUST_STORE_PWD} -destkeypass ${CA_TRUST_STORE_PWD} -destkeystore ./${TRUST_PATH}/${CA_TRUST_CERT_CHAIN_JKS}.jks -srckeystore ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}.p12 -srcstoretype PKCS12 -srcstorepass ${CA_TRUST_STORE_PWD} -alias ${CA_TRUST_STORE_CHAIN_ALIAS} - -keytool -list -v -keystore ./${TRUST_PATH}/lwm2mtruststorechain.jks -storepass server_ks_password -storetype PKCS12 - -echo "====================================================" -echo -e "Generate and Signed the clients of our certificates: \n-${CLIENT_CERT_KEY_PREF}?-key.pem (certificate key)\n-${CLIENT_CERT_KEY_PREF}?.pem (certificate)\n-${CCLIENT_CERT_KEY_PREF}?.csr (sign request)" -echo "====================================================" - - -while [[ ${CLIENT_NUMBER} -lt ${CLIENT_FINISH} ]]; -do - CLIENT_CERT_KEY=$(client_common_name) - CLIENT_CERT_ALIAS=$(client_alias_name) - CLIENT_NUMBER=$((${CLIENT_NUMBER} + 1)) - - cfssl gencert \ - -ca ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem \ - -ca-key ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}-key.pem \ - -config ./${TRUST_PATH}/ca-config.json \ - -profile client \ - -hostname "${CLIENT_HOST_NAME}" \ - - \ - <<-CONFIG | cfssljson -bare ./${CLIENT_PATH}/${CLIENT_CERT_KEY} -{ - "CN": "${CLIENT_CERT_KEY}" -} -CONFIG - -echo "====================================================" -echo -e "Add the client certificate (${CLIENT_CERT_KEY}.pem) to keystore: ${CLIENT_JKS_FOR_TEST}.jks" -echo "====================================================" -cat ./${CLIENT_PATH}/${CLIENT_CERT_KEY}.pem ${CA_LIST_CERT_FOR_CAT} > ./${CLIENT_PATH}/${CLIENT_CERT_KEY}_chain.pem -openssl pkcs12 -export -in ./${CLIENT_PATH}/${CLIENT_CERT_KEY}_chain.pem -inkey ./${CLIENT_PATH}/${CLIENT_CERT_KEY}-key.pem -out ./${CLIENT_PATH}/${CLIENT_CERT_KEY}.p12 -name ${CLIENT_CERT_ALIAS} -CAfile ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem -caname ${CA_ROOT_ALIAS} -passin pass:${CLIENT_STORE_PWD} -passout pass:${CLIENT_STORE_PWD} -keytool -importkeystore -deststorepass ${CLIENT_STORE_PWD} -destkeypass ${CLIENT_STORE_PWD} -destkeystore ./${CLIENT_PATH}/${CLIENT_JKS_FOR_TEST}.jks -srckeystore ./${CLIENT_PATH}/${CLIENT_CERT_KEY}.p12 -srcstoretype PKCS12 -srcstorepass ${CLIENT_STORE_PWD} -alias ${CLIENT_CERT_ALIAS} - -done - -keytool -list -v -keystore ./${CLIENT_PATH}/lwm2mclient.jks -storepass client_ks_password -storetype PKCS12 - -rm ./${TRUST_PATH}/*.p12 -rm ./${TRUST_PATH}/*.csr -rm ./${TRUST_PATH}/*.json -rm ./${TRUST_PATH}/${CA_ROOT_CERT_KEY}* -rm ./${TRUST_PATH}/${CA_INTERMEDIATE_CERT_KEY_PREF}* - - -rm ./${CLIENT_PATH}/*.p12 2> /dev/null -rm ./${CLIENT_PATH}/*.csr 2> /dev/null diff --git a/application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_for_test_All.sh b/application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_for_test_All.sh deleted file mode 100755 index b3b114cb28..0000000000 --- a/application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_for_test_All.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash - -readonly INTERMEDIATE_START=0 -readonly INTERMEDIATE_FINISH=2 -readonly CLIENT_START=0 -readonly CLIENT_FINISH=5 - -IS_IHFO=false -IS_SERVER_CREATED_KEY=true -IS_TRUST_CLIENT_CREATED_KEY=true - -cd -- "$( - dirname "${0}" -)" || exit 1 - -Help() -{ - # Display Help - echo "Description of the script functions." - echo - echo "Syntax: scriptTemplate [-g|h|v|V]" - echo "options:" - echo "h Print this Help." - echo "v Verbose mode." - echo "V Print software version and exit." - echo -} - -if [ "$1" == "-h" ] ; then - echo -e "Usage 2: ./`basename $0` \"Information is not displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are generated\"" - echo -e "Usage 1: ./`basename $0` true \"Information is displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are generated\"" - echo -e "Usage 3: ./`basename $0` true false \"Information is displayed\" : \"Keys for the server are not generated\" : \"Keys for the clients and trusts are generated\"" - echo -e "Usage 4: ./`basename $0` true false false \"Information is displayed\" : \"Keys for the server are not generated\" : \"Keys for the clients and trusts are not generated\"" - echo -e "Usage 4: ./`basename $0` true true false \"Information is displayed\" : \"Keys for the server are generated\" : \"Keys for the clients and trusts are not generated\"" - echo "This Help File: ./`basename $0` -h" - exit 0 -fi - -if [ -n "$1" ]; then - IS_IHFO=$1 -fi - -if [ -n "$2" ]; then - IS_SERVER_CREATED_KEY=$2 -fi - -if [ -n "$3" ]; then - IS_TRUST_CLIENT_CREATED_KEY=$3 -fi - -if [ "$IS_IHFO" = false ] ; then - if [ "$IS_SERVER_CREATED_KEY" = true ] ; then - ./lwm2m_cfssl_chain_server_for_test.sh > /dev/null 2>&1 & - fi - if [ "$IS_TRUST_CLIENT_CREATED_KEY" = true ] ; then - ./lwM2M_cfssl_chain_trusts_and_clients_for_test.sh ${INTERMEDIATE_START} ${INTERMEDIATE_FINISH} ${CLIENT_START} ${CLIENT_FINISH} > /dev/null 2>&1 & - fi -else - if [ "$IS_SERVER_CREATED_KEY" = true ] ; then - ./lwm2m_cfssl_chain_server_for_test.sh - fi - if [ "$IS_TRUST_CLIENT_CREATED_KEY" = true ] ; then - ./lwM2M_cfssl_chain_trusts_and_clients_for_test.sh ${INTERMEDIATE_START} ${INTERMEDIATE_FINISH} ${CLIENT_START} ${CLIENT_FINISH} - fi -fi \ No newline at end of file diff --git a/application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_server_for_test.sh b/application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_server_for_test.sh deleted file mode 100755 index efe6ed46dd..0000000000 --- a/application/src/test/resources/lwm2m/credentials/shell/lwm2m_cfssl_chain_server_for_test.sh +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/env bash - -# REF: https://github.com/cloudflare/cfssl - -# Change working directory -cd -- "$( - dirname "${0}" -)" || exit 1 - -readonly CA_ROOT_CERT_KEY="ca-root" -readonly CA_ROOT_ALIAS="root" -readonly CA_INTERMEDIATE_CERT_KEY_PREF="intermediate_ca" -CA_INTERMEDIATE_NUMBER=0 -CA_LIST_CERT_FOR_CAT="" - -readonly CF_COMMANDS=" - cfssl - cfssljson -" - -readonly SERVER_JKS_FOR_TEST="lwm2mserver" -readonly STORE_PASS_PWD="server_ks_password" -readonly SERVER_PATH="Server" -readonly SERVER_CERT_KEY="lwm2mserver" -readonly SERVER_CERT_CHAIN="lwm2mserver_chain" -readonly SERVER_CERT_ALIAS="server" -readonly BS_SERVER_CERT_KEY="lwm2mserverbs" -readonly BS_SERVER_CERT_CHAIN="lwm2mserverbs_chain" -readonly BS_SERVER_CERT_ALIAS="bootstrap" - -SERVER_HOST_NAME="localhost.localdomain" -SERVER_LOCAL_HOST_NAME="localhost" -SERVER_PUBLIC_HOST_NAMES="-" - -intermediate_common_name() { - echo "${CA_INTERMEDIATE_CERT_KEY_PREF}${CA_INTERMEDIATE_NUMBER}" -} - -set_list_sert_for_cat() { - local first="$1" - echo "$first ${CA_LIST_CERT_FOR_CAT}" -} - - -# Change working directory -rm -rf ${SERVER_PATH} -mkdir -p ${SERVER_PATH} - -cd -- "$( - dirname ./${SERVER_PATH} -)" || exit 1 - - -rm *.csr -rm *.p12 -rm *.json -rm *.pem -rm *.jks - -CA_INTERMEDIATE_CERT_SIGN=${CA_ROOT_CERT_KEY} -CA_INTERMEDIATE_CERT_KEY=$(intermediate_common_name) -CA_INTERMEDIATE_NUMBER=$((${CA_INTERMEDIATE_NUMBER} + 1)) -CA_LIST_CERT_FOR_CAT="" - -for COMMAND in ${CF_COMMANDS}; do - if ! command -v ${COMMAND} &> /dev/null; then - echo "ERROR: Missing command ${COMMAND}" >&2 - echo "Install the package from: https://pkg.cfssl.org/" >&2 - exit 1 - fi -done - -tee ./${SERVER_PATH}/ca-config.json 1> /dev/null <<-CONFIG -{ - "signing": { - "default": { - "expiry": "8760h", - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ] - }, - "profiles": { - "server": { - "expiry": "43800h", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "signing", - "key encipherment", - "server auth" - ] - }, - "client": { - "expiry": "43800h", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "signing", - "key encipherment", - "client auth" - ] - }, - "client-server": { - "expiry": "43800h", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "signing", - "key encipherment", - "server auth", - "client auth" - ] - } - } - } -} -CONFIG - -tee ./${SERVER_PATH}/ca-root-to-intermediate-config.json 1> /dev/null <<-CONFIG -{ - "signing": { - "default": { - "expiry": "43800h", - "ca_constraint": { - "is_ca": true, - "max_path_len": 0, - "max_path_len_zero": true - }, - "key": { - "algo": "ecdsa", - "size": 256 - }, - "usages": [ - "digital signature", - "cert sign", - "crl sign", - "signing" - ] - } - } -} -CONFIG - -echo "====================================================" -echo -e "Generate the root of certificates: \n-${CA_ROOT_KEY}-key.pem (certificate key)\n-${CA_ROOT_KEY}.pem (certificate)\n-${CA_ROOT_KEY}.csr (sign request)" -echo "====================================================" -cfssl genkey \ - -initca \ - - \ - <<-CONFIG | cfssljson -bare ./${SERVER_PATH}/${CA_ROOT_CERT_KEY} -{ - "CN": "ROOT CA for servers", - "key": { - "algo": "ecdsa", - "size": 256 - }, - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ], - "ca": { - "expiry": "131400h" - } -} -CONFIG -CA_LIST_CERT_FOR_CAT=$(set_list_sert_for_cat ./${SERVER_PATH}/${CA_ROOT_CERT_KEY}.pem) - -echo "====================================================" -echo -e "Generate and Signed the first intermediates of our certificates: \n-${CA_INTERMEDIATE_CERT_KEY}-key.pem (certificate key)\n-${CA_INTERMEDIATE_CERT_KEY}.pem (certificate)\n-${CA_INTERMEDIATE_CERT_KEY}.csr (sign request)" -echo "====================================================" -cfssl gencert \ - -ca ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_SIGN}.pem \ - -ca-key ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_SIGN}-key.pem \ - -config ./${SERVER_PATH}/ca-root-to-intermediate-config.json \ - -hostname "${SERVER_HOST_NAME},${SERVER_LOCAL_HOST_NAME}${SERVER_PUBLIC_HOST_NAMES:+, }${SERVER_PUBLIC_HOST_NAMES}" \ - - \ - <<-CONFIG | cfssljson -bare ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY} -{ - "CN": "${CA_INTERMEDIATE_CERT_KEY}", - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ] -} -CONFIG -CA_LIST_CERT_FOR_CAT=$(set_list_sert_for_cat ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem) - - -## Lwm2m Server certificate -echo "====================================================" -echo -e "Generate and Signed the server certificate: \n-${SERVER_CERT_KEY}-key.pem (certificate key)\n-${SERVER_CERT_KEY}.pem (certificate)\n-${SERVER_CERT_KEY}.csr (sign request)" -echo "====================================================" -cfssl gencert \ - -ca ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem \ - -ca-key ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}-key.pem \ - -config ./${SERVER_PATH}/ca-config.json \ - -profile server \ - -hostname "${SERVER_HOST_NAME},${SERVER_LOCAL_HOST_NAME}${SERVER_PUBLIC_HOST_NAMES:+, }${SERVER_PUBLIC_HOST_NAMES}" \ - - \ - <<-CONFIG | cfssljson -bare ./${SERVER_PATH}/${SERVER_CERT_KEY} -{ - "CN": "${SERVER_LOCAL_HOST_NAME}" -} -CONFIG - -echo "====================================================" -echo -e "Add the server certificate (${SERVER_CERT_KEY}.pem) to keystore: ${SERVER_JKS_FOR_TEST}.jks" -echo "====================================================" -cat ./${SERVER_PATH}/${SERVER_CERT_KEY}.pem ${CA_LIST_CERT_FOR_CAT} > ./${SERVER_PATH}/${SERVER_CERT_CHAIN}.pem -openssl pkcs12 -export -in ./${SERVER_PATH}/${SERVER_CERT_CHAIN}.pem -inkey ./${SERVER_PATH}/${SERVER_CERT_KEY}-key.pem -out ./${SERVER_PATH}/${SERVER_CERT_KEY}.p12 -name ${SERVER_CERT_ALIAS} -CAfile ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem -caname ${CA_ROOT_ALIAS} -passin pass:${STORE_PASS_PWD} -passout pass:${STORE_PASS_PWD} -keytool -importkeystore -deststorepass ${STORE_PASS_PWD} -destkeypass ${STORE_PASS_PWD} -destkeystore ./${SERVER_PATH}/${SERVER_JKS_FOR_TEST}.jks -srckeystore ./${SERVER_PATH}/${SERVER_CERT_KEY}.p12 -srcstoretype PKCS12 -srcstorepass ${STORE_PASS_PWD} -alias ${SERVER_CERT_ALIAS} - - -CA_INTERMEDIATE_CERT_SIGN=${CA_INTERMEDIATE_CERT_KEY} -CA_INTERMEDIATE_CERT_KEY=$(intermediate_common_name) -CA_INTERMEDIATE_NUMBER=$((${CA_INTERMEDIATE_NUMBER} + 1)) -echo "====================================================" -echo -e "Generate and Signed the second intermediates of our certificates: \n-${CA_INTERMEDIATE_CERT_KEY}-key.pem (certificate key)\n-${CA_INTERMEDIATE_CERT_KEY}.pem (certificate)\n-${CA_INTERMEDIATE_CERT_KEY}.csr (sign request)" -echo "====================================================" -cfssl gencert \ - -ca ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_SIGN}.pem \ - -ca-key ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_SIGN}-key.pem \ - -config ./${SERVER_PATH}/ca-root-to-intermediate-config.json \ - -hostname "${SERVER_HOST_NAME},${SERVER_LOCAL_HOST_NAME}${SERVER_PUBLIC_HOST_NAMES:+, }${SERVER_PUBLIC_HOST_NAMES}" \ - - \ - <<-CONFIG | cfssljson -bare ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY} -{ - "CN": "${CA_INTERMEDIATE_CERT_KEY}", - "names": [ - { - "C": "UK", - "ST": "Kyiv city", - "L": "Kyiv", - "O": "Thingsboard", - "OU": "DEVELOPER_TEST" - } - ] -} -CONFIG -CA_LIST_CERT_FOR_CAT=$(set_list_sert_for_cat ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem) - -## Bootstrap server certificate -echo "====================================================" -echo -e "Generate and Signed the server certificate: \n-${BS_SERVER_CERT_KEY}-key.pem (certificate key)\n-${BS_SERVER_CERT_KEY}.pem (certificate)\n-${BS_SERVER_CERT_KEY}.csr (sign request)" -echo "====================================================" -cfssl gencert \ - -ca ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem \ - -ca-key ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}-key.pem \ - -config ./${SERVER_PATH}/ca-config.json \ - -profile server \ - -hostname "${SERVER_HOST_NAME},${SERVER_LOCAL_HOST_NAME}${SERVER_PUBLIC_HOST_NAMES:+, }${SERVER_PUBLIC_HOST_NAMES}" \ - - \ - <<-CONFIG | cfssljson -bare ./${SERVER_PATH}/${BS_SERVER_CERT_KEY} -{ - "CN": "${SERVER_LOCAL_HOST_NAME}" -} -CONFIG - -echo "====================================================" -echo -e "Add the Bootstrap server certificate (${BS_SERVER_CERT_KEY}.pem) to keystore: ${SERVER_JKS_FOR_TEST}.jks" -echo "====================================================" -cat ./${SERVER_PATH}/${BS_SERVER_CERT_KEY}.pem ${CA_LIST_CERT_FOR_CAT} > ./${SERVER_PATH}/${BS_SERVER_CERT_CHAIN}.pem -openssl pkcs12 -export -in ./${SERVER_PATH}/${BS_SERVER_CERT_CHAIN}.pem -inkey ./${SERVER_PATH}/${BS_SERVER_CERT_KEY}-key.pem -out ./${SERVER_PATH}/${BS_SERVER_CERT_KEY}.p12 -name ${BS_SERVER_CERT_ALIAS} -CAfile ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY}.pem -caname ${CA_ROOT_ALIAS} -passin pass:${STORE_PASS_PWD} -passout pass:${STORE_PASS_PWD} -keytool -importkeystore -deststorepass ${STORE_PASS_PWD} -destkeypass ${STORE_PASS_PWD} -destkeystore ./${SERVER_PATH}/${SERVER_JKS_FOR_TEST}.jks -srckeystore ./${SERVER_PATH}/${BS_SERVER_CERT_KEY}.p12 -srcstoretype PKCS12 -srcstorepass ${STORE_PASS_PWD} -alias ${BS_SERVER_CERT_ALIAS} - - -keytool -list -v -keystore ./${SERVER_PATH}/lwm2mserver.jks -storepass server_ks_password -storetype PKCS12 - -rm ./${SERVER_PATH}/*.p12 2> /dev/null -rm ./${SERVER_PATH}/*.csr 2> /dev/null -rm ./${SERVER_PATH}/*.json 2> /dev/null -rm ./${SERVER_PATH}/${CA_INTERMEDIATE_CERT_KEY_PREF}* 2> /dev/null -rm ./${SERVER_PATH}/${CA_ROOT_CERT_KEY}* 2> /dev/null -mv ./${SERVER_PATH}/${SERVER_CERT_KEY}-key.pem ./${SERVER_PATH}/${SERVER_CERT_KEY}_key.pem -mv ./${SERVER_PATH}/${BS_SERVER_CERT_KEY}-key.pem ./${SERVER_PATH}/${BS_SERVER_CERT_KEY}_key.pem - From 8480f219949476736a591b82095b663a4e23effc Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 1 Feb 2022 10:05:15 +0200 Subject: [PATCH 09/20] lwm2m: del info debug --- .../transport/lwm2m/server/LwM2mVersionedModelProvider.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java index 8f754bc142..8bf8c8396e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mVersionedModelProvider.java @@ -85,8 +85,6 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { this.registration = registration; this.tenantId = lwM2mClientContext.getClientByEndpoint(registration.getEndpoint()).getTenantId(); this.modelsLock = new ReentrantLock(); - log.info("tenantId: [{}]", tenantId); - log.info("models: [{}]", models); if (tenantId != null) { models.computeIfAbsent(tenantId, t -> new ConcurrentHashMap<>()); } From acc52c786404e4d6af86ff1fa219bb6468702ed4 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 3 Feb 2022 18:01:12 +0200 Subject: [PATCH 10/20] lwm2m: fix bug create new client (from TcpPort to UdpPort) --- .../server/transport/lwm2m/AbstractLwM2MIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c63901a7dc..a3468166bc 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 @@ -279,7 +279,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint, boolean isBootstrap, Security securityBs) throws Exception { clientDestroy(); client = new LwM2MTestClient(this.executor, endpoint); - int clientPort = SocketUtils.findAvailableTcpPort(); + int clientPort = SocketUtils.findAvailableUdpPort(); client.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); } From 29a551d048538e94819954601d2b34925a2c75c9 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 4 Feb 2022 15:59:12 +0200 Subject: [PATCH 11/20] lwm2m: fix bug: add afterClass "await (3 sec, closed all ports lwm2server and bootstrapServer)" --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 82 ++++-- .../transport/lwm2m/Lwm2mTestHelper.java | 27 -- .../lwm2m/client/LwM2MTestClient.java | 32 +-- .../transport/lwm2m/client/Lwm2mServer.java | 235 ++++++++++++++++++ .../rpc/AbstractRpcLwM2MIntegrationTest.java | 14 +- .../sql/RpcLwm2mIntegrationDiscoverTest.java | 2 +- .../sql/RpcLwm2mIntegrationObserveTest.java | 2 +- .../AbstractSecurityLwM2MIntegrationTest.java | 43 +--- .../LwM2MTransportBootstrapService.java | 10 +- ...LwM2MBootstrapConfigStoreTaskProvider.java | 2 +- .../server/DefaultLwM2mTransportService.java | 10 +- .../lwm2m/server/LwM2MNetworkConfig.java | 10 - 12 files changed, 347 insertions(+), 122 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/client/Lwm2mServer.java 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 a3468166bc..fd785e9de0 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 @@ -19,8 +19,10 @@ import com.fasterxml.jackson.core.type.TypeReference; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.leshan.client.californium.LeshanClient; import org.eclipse.leshan.client.object.Security; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.springframework.util.SocketUtils; @@ -64,6 +66,8 @@ 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 java.io.IOException; +import java.net.ServerSocket; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -73,7 +77,9 @@ import java.util.List; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import static org.awaitility.Awaitility.await; import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; @@ -97,6 +103,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest public static final int securityPort = 5686; public static final int portBs = 5687; public static final int securityPortBs = 5688; + public static final int[] SERVERS_PORT_NUMBERS = {port, securityPort, portBs, securityPortBs}; public static final String host = "localhost"; public static final String hostBs = "localhost"; @@ -156,16 +163,29 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest protected DeviceProfile deviceProfile; protected ScheduledExecutorService executor; protected TbTestWebSocketClient wsClient; - protected LwM2MTestClient client; + protected LwM2MTestClient lwM2MTestClient; private String[] resources; - public AbstractLwM2MIntegrationTest() { + @Before + public void startInit() throws Exception { + init(); + } + + @After + public void after() { + wsClient.close(); + clientDestroy(); + executor.shutdownNow(); } - public void init() throws Exception { + @AfterClass + public static void afterClass () { + awaitServersDestroy(); + } + + private void init () throws Exception { executor = Executors.newScheduledThreadPool(10, ThingsBoardThreadFactory.forName("test-lwm2m-scheduled")); loginTenantAdmin(); - for (String resourceName : this.resources) { TbResource lwModel = new TbResource(); lwModel.setResourceType(ResourceType.LWM2M_MODEL); @@ -181,18 +201,6 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest wsClient = buildAndConnectWebSocketClient(); } - @Before - public void beforeTest() throws Exception { - this.init(); - } - - @After - public void after() { - wsClient.close(); - clientDestroy(); - executor.shutdownNow(); - } - public void basicTestConnectionObserveTelemetry(Security security, LwM2MDeviceCredentials deviceCredentials, Configuration coapConfig, @@ -277,15 +285,20 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest } public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint, boolean isBootstrap, Security securityBs) throws Exception { - clientDestroy(); - client = new LwM2MTestClient(this.executor, endpoint); + this.clientDestroy(); + lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableUdpPort(); - client.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); + lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); } private void clientDestroy() { - if (client != null) { - client.destroy(); + try { + if (lwM2MTestClient != null) { + lwM2MTestClient.destroy(); + awaitClientDestroy(lwM2MTestClient.getLeshanClient()); + } + } catch (Exception e) { + log.error("", e); } } @@ -338,4 +351,31 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest credentials.setBootstrap(bootstrapCredentials); return credentials; } + + private static void awaitServersDestroy() { + await("One of servers ports number is not free") + .atMost(3000, TimeUnit.MILLISECONDS) + .until(() -> isServerPortsAvailable() == null); + } + + + private static String isServerPortsAvailable() { + for (int port : SERVERS_PORT_NUMBERS) { + try (ServerSocket serverSocket = new ServerSocket(port)) { + serverSocket.close(); + Assert.assertEquals(true, serverSocket.isClosed()); + } catch (IOException e) { + log.warn(String.format("Port %n still in use", port)); + return (String.format("Port %n still in use", port)); + } + } + return null; + } + + private static void awaitClientDestroy(LeshanClient leshanClient) { + await("Destroy LeshanClient: delete All is registered Servers.") + .atMost(2000, TimeUnit.MILLISECONDS) + .until(() -> leshanClient.getRegisteredServers().size() == 0); + } + } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index b8e3017236..f662b61d91 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -17,33 +17,6 @@ package org.thingsboard.server.transport.lwm2m; public class Lwm2mTestHelper { -// // Server -// public static final int SECURE_PORT = 5686; -// public static final int SECURE_PORT_BS = 5688; -// -//// public static final String HOST = "localhost"; -//// public static final int PORT = 5685; -////public static final String URI = "coap://" + HOST + ":" + PORT; -//public static final String SECURE_URI = "coaps://" + HOST + ":" + SECURE_PORT; -// public static final Configuration COAP_CONFIG = new Configuration().set(EXCHANGE_LIFETIME , 200, TimeUnit.SECONDS).set(COAP_PORT, PORT).set(COAP_SECURE_PORT, SECURE_PORT); -// public static final Security SECURITY_NO_SEC = noSec(URI, SHORT_SERVER_ID); -// -// public static final int PORT_BS = 5687; -// -// public static final String HOST_BS = "localhost"; -// public static final int SHORT_SERVER_ID = 123; -// public static final int SHORT_SERVER_ID_BS = 111; -// -// -// public static final Configuration SECURE_COAP_CONFIG = COAP_CONFIG.set(COAP_SECURE_PORT, SECURE_PORT); -// public static final Configuration COAP_CONFIG_BS = new Configuration().set(COAP_PORT, PORT_BS); -// -// -// public static final String URI_BS = "coap://" + HOST_BS + ":" + PORT_BS; -// -// public static final String SECURE_URI_BS = "coaps://" + HOST_BS + ":" + SECURE_PORT_BS; - - // Models public static final String[] resources = new String[]{"0.xml", "1.xml", "2.xml", "3.xml", "5.xml", "6.xml", "9.xml", "19.xml", "3303.xml"}; public static final int BINARY_APP_DATA_CONTAINER = 19; 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 c079513841..6e055783fe 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 @@ -43,7 +43,6 @@ import org.eclipse.leshan.core.request.RegisterRequest; import org.eclipse.leshan.core.request.UpdateRequest; import org.junit.Assert; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; - import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -92,12 +91,12 @@ public class LwM2MTestClient { private final ScheduledExecutorService executor; private final String endpoint; - private LeshanClient client; + private LeshanClient leshanClient; private Security lwm2mSecurity; private Security lwm2mSecurityBs; - private Server lwm2mServer; - private Server lwm2mServerBs; + private Lwm2mServer lwm2mServer; + private Lwm2mServer lwm2mServerBs; private SimpleLwM2MDevice lwM2MDevice; private FwLwM2MDevice fwLwM2MDevice; private SwLwM2MDevice swLwM2MDevice; @@ -108,7 +107,7 @@ public class LwM2MTestClient { private Set clientStates; public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, int shortServerId, int shortServerIdBs, Security securityBs) throws InvalidDDFFileException, IOException { - Assert.assertNull("client already initialized", client); + Assert.assertNull("client already initialized", leshanClient); List models = new ArrayList<>(); for (String resourceName : resources) { models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName)); @@ -125,14 +124,14 @@ public class LwM2MTestClient { initializer.setInstancesForObject(SECURITY, instances); } if (isBootstrap) { - initializer.setInstancesForObject(SERVER, lwm2mServerBs = new Server(shortServerIdBs, 300)); + initializer.setInstancesForObject(SERVER, lwm2mServerBs = new Lwm2mServer(shortServerIdBs, 300)); } else { if (securityBs == null) { - initializer.setInstancesForObject(SERVER, lwm2mServer = new Server(shortServerId, 300)); + initializer.setInstancesForObject(SERVER, lwm2mServer = new Lwm2mServer(shortServerId, 300)); } else { - lwm2mServerBs = new Server(shortServerIdBs, 300); + lwm2mServerBs = new Lwm2mServer(shortServerIdBs, 300); lwm2mServerBs.setId(0); - lwm2mServer =new Server(shortServerId, 300); + lwm2mServer = new Lwm2mServer(shortServerId, 300); lwm2mServer.setId(1); LwM2mInstanceEnabler[] instances = new LwM2mInstanceEnabler[]{lwm2mServerBs, lwm2mServer}; initializer.setClassForObject(SERVER, Server.class); @@ -170,7 +169,7 @@ public class LwM2MTestClient { clientState = ON_INIT; clientStates = new HashSet<>(); clientStates.add(clientState); - client = builder.build(); + leshanClient = builder.build(); LwM2mClientObserver observer = new LwM2mClientObserver() { @Override @@ -275,15 +274,16 @@ public class LwM2MTestClient { clientStates.add(clientState); } }; - this.client.addObserver(observer); + this.leshanClient.addObserver(observer); + if (!isRpc) { - client.start(); + leshanClient.start(); } } public void destroy() { - if (client != null) { - client.destroy(true); + if (leshanClient != null) { + leshanClient.destroy(true); } if (lwm2mSecurityBs != null) { lwm2mSecurityBs = null; @@ -315,8 +315,8 @@ public class LwM2MTestClient { } public void start() { - if (client != null) { - client.start(); + if (leshanClient != null) { + leshanClient.start(); } } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/Lwm2mServer.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/Lwm2mServer.java new file mode 100644 index 0000000000..d4bac0a683 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/Lwm2mServer.java @@ -0,0 +1,235 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.client; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.client.resource.BaseInstanceEnabler; +import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler; +import org.eclipse.leshan.client.servers.ServerIdentity; +import org.eclipse.leshan.core.model.ObjectModel; +import org.eclipse.leshan.core.model.ResourceModel.Type; +import org.eclipse.leshan.core.node.LwM2mResource; +import org.eclipse.leshan.core.request.BindingMode; +import org.eclipse.leshan.core.response.ExecuteResponse; +import org.eclipse.leshan.core.response.ReadResponse; +import org.eclipse.leshan.core.response.WriteResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; +import java.util.Objects; + +/** + * A simple {@link LwM2mInstanceEnabler} for the Server (1) object. + */ +@Slf4j +public class Lwm2mServer extends BaseInstanceEnabler { + + private static final Logger LOG = LoggerFactory.getLogger(Lwm2mServer.class); + + private final static List supportedResources = Arrays.asList(0, 1, 2, 3, 6, 7, 8, 22); + + private int shortServerId; + private long lifetime; + private Long defaultMinPeriod; + private Long defaultMaxPeriod; + private EnumSet binding; + private BindingMode preferredTransport; + private boolean notifyWhenDisable; + + public Lwm2mServer() { + // should only be used at bootstrap time + } + + public Lwm2mServer(int shortServerId, long lifetime, EnumSet binding, boolean notifyWhenDisable, + BindingMode preferredTransport) { + this.shortServerId = shortServerId; + this.lifetime = lifetime; + this.binding = binding; + this.notifyWhenDisable = notifyWhenDisable; + this.preferredTransport = preferredTransport; + } + + public Lwm2mServer(int shortServerId, long lifetime) { + this(shortServerId, lifetime, EnumSet.of(BindingMode.U), false, BindingMode.U); + } + + @Override + public ReadResponse read(ServerIdentity identity, int resourceid) { + if (!identity.isSystem()) + LOG.debug("Read on Server resource /{}/{}/{}", getModel().id, getId(), resourceid); + + switch (resourceid) { + case 0: // short server ID + return ReadResponse.success(resourceid, shortServerId); + + case 1: // lifetime + return ReadResponse.success(resourceid, lifetime); + + case 2: // default min period + if (null == defaultMinPeriod) + return ReadResponse.notFound(); + return ReadResponse.success(resourceid, defaultMinPeriod); + + case 3: // default max period + if (null == defaultMaxPeriod) + return ReadResponse.notFound(); + return ReadResponse.success(resourceid, defaultMaxPeriod); + + case 6: // notification storing when disable or offline + return ReadResponse.success(resourceid, notifyWhenDisable); + + case 7: // binding + return ReadResponse.success(resourceid, BindingMode.toString(binding)); + + case 22: // preferred transport + if (preferredTransport == null) + return ReadResponse.notFound(); + return ReadResponse.success(resourceid, preferredTransport.toString()); + + default: + return super.read(identity, resourceid); + } + } + + @Override + public WriteResponse write(ServerIdentity identity, boolean replace, int resourceid, LwM2mResource value) { + if (!identity.isSystem()) + log.debug("Write on Server resource /{}/{}/{}", getModel().id, getId(), resourceid); + + switch (resourceid) { + case 0: + if (value.getType() != Type.INTEGER) { + return WriteResponse.badRequest("invalid type"); + } + int previousShortServerId = shortServerId; + shortServerId = ((Long) value.getValue()).intValue(); + if (previousShortServerId != shortServerId) + fireResourceChange(resourceid); + return WriteResponse.success(); + + case 1: + if (value.getType() != Type.INTEGER) { + return WriteResponse.badRequest("invalid type"); + } + long previousLifetime = lifetime; + lifetime = (Long) value.getValue(); + if (previousLifetime != lifetime) + fireResourceChange(resourceid); + return WriteResponse.success(); + + case 2: + if (value.getType() != Type.INTEGER) { + return WriteResponse.badRequest("invalid type"); + } + Long previousDefaultMinPeriod = defaultMinPeriod; + defaultMinPeriod = (Long) value.getValue(); + if (!Objects.equals(previousDefaultMinPeriod, defaultMinPeriod)) + fireResourceChange(resourceid); + return WriteResponse.success(); + + case 3: + if (value.getType() != Type.INTEGER) { + return WriteResponse.badRequest("invalid type"); + } + Long previousDefaultMaxPeriod = defaultMaxPeriod; + defaultMaxPeriod = (Long) value.getValue(); + if (!Objects.equals(previousDefaultMaxPeriod, defaultMaxPeriod)) + fireResourceChange(resourceid); + return WriteResponse.success(); + + case 6: // notification storing when disable or offline + if (value.getType() != Type.BOOLEAN) { + return WriteResponse.badRequest("invalid type"); + } + boolean previousNotifyWhenDisable = notifyWhenDisable; + notifyWhenDisable = (boolean) value.getValue(); + if (previousNotifyWhenDisable != notifyWhenDisable) + fireResourceChange(resourceid); + return WriteResponse.success(); + + case 7: // binding + if (value.getType() != Type.STRING) { + return WriteResponse.badRequest("invalid type"); + } + try { + EnumSet previousBinding = binding; + binding = BindingMode.parse((String) value.getValue()); + if (!Objects.equals(previousBinding, binding)) + fireResourceChange(resourceid); + return WriteResponse.success(); + } catch (IllegalArgumentException e) { + return WriteResponse.badRequest("invalid value"); + } + case 22: // preferredTransport + if (value.getType() != Type.STRING) { + return WriteResponse.badRequest("invalid type"); + } + try { + BindingMode previousPreferedTransport = preferredTransport; + preferredTransport = BindingMode.valueOf((String) value.getValue()); + if (!Objects.equals(previousPreferedTransport, preferredTransport)) + fireResourceChange(resourceid); + return WriteResponse.success(); + } catch (IllegalArgumentException e) { + return WriteResponse.badRequest("invalid value"); + } + + default: + return super.write(identity, replace, resourceid, value); + } + } + + @Override + public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) { + log.info("Execute on Server resource /{}/{}/{}", getModel().id, getId(), resourceid); + if (resourceid == 8) { + getLwM2mClient().triggerRegistrationUpdate(identity); + return ExecuteResponse.success(); + } else if (resourceid == 9) { + boolean success = getLwM2mClient().triggerClientInitiatedBootstrap(true); + if (success) { + return ExecuteResponse.success(); + } + else { + return ExecuteResponse.badRequest("probably no bootstrap server configured"); + } + } else { + return super.execute(identity, resourceid, params); + } + } + + @Override + public void reset(int resourceid) { + switch (resourceid) { + case 2: + defaultMinPeriod = null; + break; + case 3: + defaultMaxPeriod = null; + break; + default: + super.reset(resourceid); + } + } + + @Override + public List getAvailableResourceIds(ObjectModel model) { + return supportedResources; + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 1105e94ccd..669d8de55a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -76,16 +76,18 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg } @Before - public void beforeTest() throws Exception { + public void startInitRPC() throws Exception { + initRpc(); + } + + private void initRpc () throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); - init(); createNewClient(SECURITY_NO_SEC, COAP_CONFIG, true, endpoint, false, null); - expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); expectedInstances = ConcurrentHashMap.newKeySet(); expectedObjectIdVerInstances = ConcurrentHashMap.newKeySet(); - client.getClient().getObjectTree().getObjectEnablers().forEach((key, val) -> { + lwM2MTestClient.getLeshanClient().getObjectTree().getObjectEnablers().forEach((key, val) -> { if (key > 0) { String objectVerId = "/" + key; if (!val.getObjectModel().version.equals("1.0")) { @@ -100,7 +102,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg }); } }); - String ver_Id_0 = client.getClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_0).version; + String ver_Id_0 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_0).version; if ("1.0".equals(ver_Id_0)) { objectIdVer_0 = "/" + OBJECT_ID_0; } else { @@ -145,7 +147,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg final Device device = createDevice(deviceCredentials, endpoint); deviceId = device.getId().getId().toString(); - client.start(); + lwM2MTestClient.start(); } protected String pathIdVerToObjectId(String pathIdVer) { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java index a4870b3486..5fd3c09d06 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java @@ -124,7 +124,7 @@ public class RpcLwm2mIntegrationDiscoverTest extends AbstractRpcLwM2MIntegration String expectedInstance = (String) expectedInstances.stream().findFirst().get(); String expectedObjectInstanceId = pathIdVerToObjectId(expectedInstance); LwM2mPath expectedPath = new LwM2mPath(expectedObjectInstanceId); - int expectedResource = client.getClient().getObjectTree().getObjectEnablers().get(expectedPath.getObjectId()).getObjectModel().resources.entrySet().stream().findAny().get().getKey(); + int expectedResource = lwM2MTestClient.getLeshanClient().getObjectTree().getObjectEnablers().get(expectedPath.getObjectId()).getObjectModel().resources.entrySet().stream().findAny().get().getKey(); String expected = expectedInstance + "/" + expectedResource; String actualResult = sendDiscover(expected); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java index 6aab036aa8..d9631928a7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java @@ -70,7 +70,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT public void testObserveWithBadVersion_Result_BadRequest_ErrorMsg_BadVersionMustBe1_0() throws Exception { String expectedInstance = (String) expectedInstances.stream().filter(path -> !((String)path).contains("_")).findFirst().get(); LwM2mPath expectedPath = new LwM2mPath(expectedInstance); - int expectedResource = client.getClient().getObjectTree().getObjectEnablers().get(expectedPath.getObjectId()).getObjectModel().resources.entrySet().stream().findAny().get().getKey(); + int expectedResource = lwM2MTestClient.getLeshanClient().getObjectTree().getObjectEnablers().get(expectedPath.getObjectId()).getObjectModel().resources.entrySet().stream().findAny().get().getKey(); String expectedId = "/" + expectedPath.getObjectId() + "_1.2" + "/" + expectedPath.getObjectInstanceId() + "/" + expectedResource; String actualResult = sendObserve("Observe", expectedId); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 2f1d528573..fa4b601ed0 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -15,12 +15,10 @@ */ package org.thingsboard.server.transport.lwm2m.security; -import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; -import org.eclipse.leshan.core.ResponseCode; import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; @@ -63,9 +61,7 @@ import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; import static org.eclipse.leshan.client.object.Security.noSecBootstap; -import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; @@ -193,22 +189,12 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); device.getId().getId().toString(); - client.start(); + lwM2MTestClient.start(); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> finishState.equals(client.getClientState())); - Assert.assertEquals(expectedStatuses, client.getClientStates()); - - client.destroy(); - if (ON_BOOTSTRAP_SUCCESS != finishState) { - expectedStatuses.add(ON_DEREGISTRATION_STARTED); - expectedStatuses.add(ON_DEREGISTRATION_SUCCESS); - await(awaitAlias) - .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> ON_DEREGISTRATION_SUCCESS.equals(client.getClientState())); - Assert.assertEquals(expectedStatuses, client.getClientStates()); - } + .until(() -> finishState.equals(lwM2MTestClient.getClientState())); + Assert.assertEquals(expectedStatuses, lwM2MTestClient.getClientStates()); } @@ -242,30 +228,21 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceId = device.getId().getId().toString(); - client.start(); + lwM2MTestClient.start(); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> ON_REGISTRATION_SUCCESS.equals(client.getClientState())); - Assert.assertEquals(expectedStatusesLwm2m, client.getClientStates()); + .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); + Assert.assertEquals(expectedStatusesLwm2m, lwM2MTestClient.getClientStates()); String executedPath = getObjectIdVer_1() + "/0/" + RESOURCE_ID_9; - String actualResult = sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); - ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); - assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText()); - + sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); expectedStatusesBs.add(ON_DEREGISTRATION_STARTED); expectedStatusesBs.add(ON_DEREGISTRATION_SUCCESS); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> ON_REGISTRATION_SUCCESS.equals(client.getClientState())); - Assert.assertEquals(expectedStatusesBs, client.getClientStates()); - - client.destroy(); - await(awaitAlias) - .atMost(1000, TimeUnit.MILLISECONDS) - .until(() -> ON_DEREGISTRATION_SUCCESS.equals(client.getClientState())); - Assert.assertEquals(expectedStatusesBs, client.getClientStates()); + .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); + Assert.assertEquals(expectedStatusesBs, lwM2MTestClient.getClientStates()); } protected List getBootstrapServerCredentialsSecure(LwM2MSecurityMode mode, LwM2MProfileBootstrapConfigType bootstrapConfigType) { @@ -423,7 +400,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M } private String getObjectIdVer_1() { - String ver_Id_0 = client.getClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version; + String ver_Id_0 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version; String objectIdVer_1; if ("1.0".equals(ver_Id_0)) { objectIdVer_1 = "/" + OBJECT_ID_1; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index ff40289884..fc7893768b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -67,9 +67,13 @@ public class LwM2MTransportBootstrapService { @PreDestroy public void shutdown() { - log.info("Stopping LwM2M transport bootstrap server!"); - server.destroy(); - log.info("LwM2M transport bootstrap server stopped!"); + try { + log.info("Stopping LwM2M transport bootstrap server!"); + server.destroy(); + log.info("LwM2M transport bootstrap server stopped!"); + } catch (Exception e) { + log.error("", e); + } } public LeshanBootstrapServer getLhBootstrapServer() { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java index cf4809f11a..b2b856b807 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java @@ -173,7 +173,7 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi if (shId instanceof Long) { shortId = ((Long) shId).intValue(); } else { - shortId = ((Integer) shId).intValue(); + shortId = (int) shId; } serverInstances.put(shortId, instance.getId()); }); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 8f6fe7cdb2..e8d6ffb7fa 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -99,9 +99,13 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @PreDestroy public void shutdown() { - log.info("Stopping LwM2M transport server!"); - server.destroy(); - log.info("LwM2M transport server stopped!"); + try { + log.info("Stopping LwM2M transport server!"); + server.destroy(); + log.info("LwM2M transport server stopped!"); + } catch (Exception e) { + log.error("", e); + } } private LeshanServer getLhServer() { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java index f3ab8d2cb8..8aed4ef9b4 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MNetworkConfig.java @@ -31,16 +31,6 @@ public class LwM2MNetworkConfig { Configuration coapConfig = new Configuration(); coapConfig.set(CoapConfig.COAP_PORT, serverPortNoSec); coapConfig.set(CoapConfig.COAP_SECURE_PORT, serverSecurePort); - /** - Example:Property for large packet: - #NetworkConfig config = new Configuration(); - #config.sett(CoapConfig.MAX_MESSAGE_SIZE,32); - #config.set(CoapConfig.PREFERRED_BLOCK_SIZE,32); - #config.set(CoapConfig.MAX_RESOURCE_BODY_SIZE,2048); - #config.set(CoapConfig.MAX_RETRANSMIT,3); - #config.set(CoapConfig.MAX_TRANSMIT_WAIT,120000); - */ - /** Property to indicate if the response should always include the Block2 option \ when client request early blockwise negociation but the response can be sent on one packet. From 974d4cb338b0ec41085c1c3071fbb898de097fa8 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 8 Feb 2022 16:10:14 +0200 Subject: [PATCH 12/20] lwm2m: fix bug: client.destroy after newClientCreate and client registered on the server --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 10 ++- .../transport/lwm2m/Lwm2mTestHelper.java | 1 + .../lwm2m/client/LwM2MTestClient.java | 2 +- .../client/LwM2mBinaryAppDataContainer.java | 7 +- .../lwm2m/client/SimpleLwM2MDevice.java | 26 ++++++- .../ota/sql/OtaLwM2MIntegrationTest.java | 6 -- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 48 ++++++------ .../sql/RpcLwm2mIntegrationExecuteTest.java | 7 +- .../sql/RpcLwm2mIntegrationObserveTest.java | 76 +++++++++++-------- .../rpc/sql/RpcLwm2mIntegrationReadTest.java | 25 +++++- .../AbstractSecurityLwM2MIntegrationTest.java | 23 +++--- .../{logback.xml => logback-test.xml} | 0 .../server/client/LwM2mClientContextImpl.java | 7 +- .../uplink/DefaultLwM2mUplinkMsgHandler.java | 12 +-- 14 files changed, 158 insertions(+), 92 deletions(-) rename application/src/test/resources/{logback.xml => logback-test.xml} (100%) 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 fd785e9de0..5786cf985d 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 @@ -84,6 +84,7 @@ import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; import static org.eclipse.leshan.client.object.Security.noSecBootstap; +import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; @@ -235,7 +236,11 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest Assert.assertEquals(device.getId(), eData.get(0).getEntityId()); Assert.assertNotNull(eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES)); var tsValue = eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("batteryLevel"); - Assert.assertEquals(42, Long.parseLong(tsValue.getValue())); + Assert.assertThat(Long.parseLong(tsValue.getValue()), instanceOf(Long.class)); + int expectedMax = 50; + int expectedMin = 5; + Assert.assertTrue(expectedMax >= Long.parseLong(tsValue.getValue())); + Assert.assertTrue(expectedMin <= Long.parseLong(tsValue.getValue())); } protected void createDeviceProfile(Lwm2mDeviceProfileTransportConfiguration transportConfiguration) throws Exception { @@ -289,6 +294,9 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableUdpPort(); lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); + if (!isRpc) { + Thread.sleep(1000); + } } private void clientDestroy() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index f662b61d91..8ff0962811 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -46,6 +46,7 @@ public class Lwm2mTestHelper { public static final String RESOURCE_ID_NAME_3_14 = "UtfOffset"; public static final String RESOURCE_ID_NAME_19_0_0 = "dataRead"; public static final String RESOURCE_ID_NAME_19_1_0 = "dataWrite"; + public static final String RESOURCE_ID_NAME_19_0_3 = "dataDescription"; public enum LwM2MClientState { 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 6e055783fe..a40922d136 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 @@ -138,7 +138,7 @@ public class LwM2MTestClient { initializer.setInstancesForObject(SERVER, instances); } } - initializer.setInstancesForObject(DEVICE, lwM2MDevice = new SimpleLwM2MDevice()); + initializer.setInstancesForObject(DEVICE, lwM2MDevice = new SimpleLwM2MDevice(executor)); initializer.setInstancesForObject(FIRMWARE, fwLwM2MDevice = new FwLwM2MDevice()); initializer.setInstancesForObject(SOFTWARE_MANAGEMENT, swLwM2MDevice = new SwLwM2MDevice()); initializer.setClassForObject(ACCESS_CONTROL, DummyInstanceEnabler.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java index a88c795f9c..797a5da2e3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java @@ -173,7 +173,8 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements } private String getDescription() { - return this.description == null ? "meter reading" : this.description; +// return this.description == null ? "meter reading" : this.description; + return this.description; } private void setTimestamp(long time) { @@ -203,6 +204,10 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements } private Map getData() { + if (data == null) { + this.data = new HashMap<>(); + this.data.put(0, new byte[]{(byte) 0xAC}); + } return data; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java index 37d93279bf..ffd3df0a09 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java @@ -32,16 +32,39 @@ import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.PrimitiveIterator; import java.util.Random; import java.util.TimeZone; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; @Slf4j public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyable { private static final Random RANDOM = new Random(); + private static final int min = 5; + private static final int max = 50; + private static final PrimitiveIterator.OfInt randomIterator = new Random().ints(min,max + 1).iterator(); private static final List supportedResources = Arrays.asList(0, 1, 2, 3, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21); + + public SimpleLwM2MDevice() { + } + + public SimpleLwM2MDevice(ScheduledExecutorService executorService) { + try { + executorService.scheduleWithFixedDelay(() -> { + fireResourceChange(9); + } + , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN + } catch (Throwable e) { + log.error("[{}]Throwable", e.toString()); + e.printStackTrace(); + } + } + + @Override public ReadResponse read(ServerIdentity identity, int resourceId) { if (!identity.isSystem()) @@ -135,7 +158,8 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl } private int getBatteryLevel() { - return 42; + return randomIterator.nextInt(); +// return 42; } private long getMemoryFree() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index e572b854b5..8173b39b5c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -100,9 +100,6 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, false, null); - - Thread.sleep(1000); - device.setFirmwareId(createFirmware().getId()); final Device savedDevice = doPost("/api/device", device, Device.class); @@ -126,9 +123,6 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, false, null); - - Thread.sleep(1000); - device.setFirmwareId(createFirmware().getId()); final Device savedDevice = doPost("/api/device", device, Device.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 669d8de55a..d80b556d72 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -60,7 +60,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected String objectInstanceIdVer_1; protected String objectIdVer_0; protected String objectIdVer_2; - private static final Predicate PREDICATE_3 = path -> (!((String) path).contains("/" + TEMPERATURE_SENSOR) && ((String) path).contains("/" + DEVICE)); + private static final Predicate PREDICATE_3 = path -> (!((String) path).startsWith("/" + TEMPERATURE_SENSOR) && ((String) path).startsWith("/" + DEVICE)); protected String objectIdVer_3; protected String objectInstanceIdVer_3; protected String objectInstanceIdVer_5; @@ -70,6 +70,8 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected String objectIdVer_3303; protected static AtomicInteger endpointSequence = new AtomicInteger(); protected static String DEVICE_ENDPOINT_RPC_PREF = "deviceEndpointRpc"; + protected String idVer_3_0_9; + protected String idVer_19_0_0; public AbstractRpcLwM2MIntegrationTest() { setResources(resources); @@ -90,9 +92,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg lwM2MTestClient.getLeshanClient().getObjectTree().getObjectEnablers().forEach((key, val) -> { if (key > 0) { String objectVerId = "/" + key; - if (!val.getObjectModel().version.equals("1.0")) { - objectVerId += ("_" + val.getObjectModel().version); - } + objectVerId += ("_" + val.getObjectModel().version); expectedObjects.add("/" + key); expectedObjectIdVers.add(objectVerId); String finalObjectVerId = objectVerId; @@ -103,38 +103,37 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg } }); String ver_Id_0 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_0).version; - if ("1.0".equals(ver_Id_0)) { - objectIdVer_0 = "/" + OBJECT_ID_0; - } else { - objectIdVer_0 = "/" + OBJECT_ID_0 + "_" + ver_Id_0; - } - objectIdVer_2 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + ACCESS_CONTROL)).findFirst().get(); - objectIdVer_3 = (String) expectedObjects.stream().filter(PREDICATE_3).findFirst().get(); - objectIdVer_19 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get(); - objectIdVer_3303 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + TEMPERATURE_SENSOR)).findFirst().get(); - objectInstanceIdVer_1 = (String) expectedObjectIdVerInstances.stream().filter(path -> (!((String) path).contains("/" + BINARY_APP_DATA_CONTAINER) && ((String) path).contains("/" + SERVER))).findFirst().get(); + objectIdVer_0 = "/" + OBJECT_ID_0 + "_" + ver_Id_0; + objectIdVer_2 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).startsWith("/" + ACCESS_CONTROL)).findFirst().get(); + objectIdVer_3 = (String) expectedObjectIdVers.stream().filter(PREDICATE_3).findFirst().get(); + objectIdVer_19 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).startsWith("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get(); + objectIdVer_3303 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).startsWith("/" + TEMPERATURE_SENSOR)).findFirst().get(); + objectInstanceIdVer_1 = (String) expectedObjectIdVerInstances.stream().filter(path -> (!((String) path).startsWith("/" + BINARY_APP_DATA_CONTAINER) && ((String) path).startsWith("/" + SERVER))).findFirst().get(); objectInstanceIdVer_3 = (String) expectedObjectIdVerInstances.stream().filter(PREDICATE_3).findFirst().get(); - objectInstanceIdVer_5 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + FIRMWARE)).findFirst().get(); - objectInstanceIdVer_9 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + SOFTWARE_MANAGEMENT)).findFirst().get(); + objectInstanceIdVer_5 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).startsWith("/" + FIRMWARE)).findFirst().get(); + objectInstanceIdVer_9 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).startsWith("/" + SOFTWARE_MANAGEMENT)).findFirst().get(); + + idVer_3_0_9 = objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9; + idVer_19_0_0 = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0; OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC = " {\n" + " \"keyName\": {\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" + + " \"" + idVer_3_0_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\": \"" + RESOURCE_ID_NAME_3_14 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" + + " \"" + idVer_19_0_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_1_0 + "\"\n" + " },\n" + " \"observe\": [\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\"\n" + + " \"" + idVer_3_0_9 + "\",\n" + + " \"" + idVer_19_0_0 + "\"\n" + " ],\n" + " \"attribute\": [\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\"\n" + " ],\n" + " \"telemetry\": [\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\",\n" + + " \"" + idVer_3_0_9 + "\",\n" + + " \"" + idVer_19_0_0 + "\",\n" + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\"\n" + " ],\n" + " \"attributeLwm2m\": {}\n" + @@ -148,6 +147,9 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg deviceId = device.getId().getId().toString(); lwM2MTestClient.start(); + + Thread.sleep(1000); + } protected String pathIdVerToObjectId(String pathIdVer) { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java index cd016de5ba..073a9fa8ed 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java @@ -121,8 +121,8 @@ public class RpcLwm2mIntegrationExecuteTest extends AbstractRpcLwM2MIntegrationT /** * bad: resource operation not "E" - * Execute {"id":"5/0/3"} - * {"result":"BAD_REQUEST","error":"Resource with /5/0/3 is not executable."} + * Execute {"id":"5_1.0/0/3"} + * {"result":"BAD_REQUEST","error":"Resource with /5_1.0/0/3 is not executable."} */ @Test public void testExecuteResourceWithOperationNotExecuteById_Result_METHOD_NOT_ALLOWED() throws Exception { @@ -130,8 +130,7 @@ public class RpcLwm2mIntegrationExecuteTest extends AbstractRpcLwM2MIntegrationT String actualResult = sendRPCExecuteById(expectedPath); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); - String expectedObjectId = pathIdVerToObjectId((String) expectedPath); - String expected = "Resource with " + expectedObjectId + " is not executable."; + String expected = "Resource with " + expectedPath + " is not executable."; String actual = rpcActualResult.get("error").asText(); assertTrue(actual.equals(expected)); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java index d9631928a7..77d6e6cfab 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java @@ -26,11 +26,11 @@ import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_14; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fromVersionedIdToObjectId; public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationTest { @@ -40,23 +40,42 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT */ @Test public void testObserveReadAllNothingObservation_Result_CONTENT_Value_Count_0() throws Exception { + String actualResultBefore = sendObserve("ObserveReadAll", null); + ObjectNode rpcActualResultBefore = JacksonUtil.fromString(actualResultBefore, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultBefore.get("result").asText()); + assertTrue(rpcActualResultBefore.get("value").asText().contains(fromVersionedIdToObjectId(idVer_3_0_9))); + assertTrue(rpcActualResultBefore.get("value").asText().contains(fromVersionedIdToObjectId(idVer_19_0_0))); String actualResult = sendObserve("ObserveCancelAll", null); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); - actualResult = sendObserve("ObserveReadAll", null); - rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); - assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); - assertEquals("[]", rpcActualResult.get("value").asText()); + assertEquals("2", rpcActualResult.get("value").asText()); + String actualResultAfter = sendObserve("ObserveReadAll", null); + ObjectNode rpcActualResultAfter = JacksonUtil.fromString(actualResultAfter, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultAfter.get("result").asText()); + String expectResultAfter = "[]"; + assertEquals( expectResultAfter, rpcActualResultAfter.get("value").asText()); } /** - * Observe {"id":"/3/0/9"} + * Observe {"id":"/3/0/0"} * @throws Exception */ @Test - public void testObserveSingleResource_Result_CONTENT_Value_SingleResource() throws Exception { - String expectedIdVer = objectInstanceIdVer_3 + "/" + RESOURCE_ID_9; - String actualResult = sendObserve("Observe", expectedIdVer); + public void testObserveSingleResourceWithout_IdVer_1_0_Result_CONTENT_Value_SingleResource() throws Exception { + String expectedId = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; + String actualResult = sendObserve("Observe", fromVersionedIdToObjectId(expectedId)); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); + assertTrue(rpcActualResult.get("value").asText().contains("LwM2mSingleResource")); + } + /** + * Observe {"id":"/3_1.0/0/14"} + * @throws Exception + */ + @Test + public void testObserveSingleResourceWith_IdVer_1_0_Result_CONTENT_Value_SingleResource() throws Exception { + String expectedId = objectInstanceIdVer_3 + "/" + RESOURCE_ID_14; + String actualResult = sendObserve("Observe", expectedId); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); assertTrue(rpcActualResult.get("value").asText().contains("LwM2mSingleResource")); @@ -100,11 +119,10 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT */ @Test public void testObserveNoImplementedResourceOnDeviceValueNull_Result_BadRequest() throws Exception { - String objectIdVer = (String) expectedObjectIdVers.stream().filter(path -> ((String)path).contains("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get(); - String expected = objectIdVer + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0; + String expected = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_3; String actualResult = sendObserve("Observe", expected); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); - String expectedValue = "values MUST NOT be null"; + String expectedValue = "value MUST NOT be null"; assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); assertEquals(expectedValue, rpcActualResult.get("error").asText()); } @@ -125,14 +143,12 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT /** * Repeated request on Observe - * Observe {"id":"/3/0/0"} + * Observe {"id":"/3/0/9"} * @throws Exception */ @Test public void testObserveRepeatedRequestObserveOnDevice_Result_BAD_REQUEST_ErrorMsg_AlreadyRegistered() throws Exception { - String expectedId = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; - sendObserve("Observe", expectedId); - String actualResult = sendObserve("Observe", expectedId); + String actualResult = sendObserve("Observe", idVer_3_0_9); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); String expected = "Observation is already registered!"; @@ -144,18 +160,18 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT * @throws Exception */ @Test - public void testObserveReadAll_Result_CONTENT_Value_Contains_Paths_Count_ObserveAll() throws Exception { - sendObserve("ObserveCancelAll", null); - String expectedId_0 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; - String expectedId_9 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_9; - sendObserve("Observe", expectedId_0); - sendObserve("Observe", expectedId_9); + public void testObserveReadAll_Result_CONTENT_Value_Contains_Paths_Count_ObserveReadAll() throws Exception { + String actualResultCancel = sendObserve("ObserveCancelAll", null); + ObjectNode rpcActualResultCancel = JacksonUtil.fromString(actualResultCancel, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultCancel.get("result").asText()); + sendObserve("Observe",idVer_19_0_0); + sendObserve("Observe", idVer_3_0_9); String actualResult = sendObserve("ObserveReadAll", null); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); String actualValues = rpcActualResult.get("value").asText(); - assertTrue(actualValues.contains(expectedId_0)); - assertTrue(actualValues.contains(expectedId_9)); + assertTrue(actualValues.contains(fromVersionedIdToObjectId(idVer_19_0_0))); + assertTrue(actualValues.contains(fromVersionedIdToObjectId(idVer_3_0_9))); assertEquals(2, actualValues.split(",").length); } @@ -167,11 +183,11 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT @Test public void testObserveCancelOneResource_Result_CONTENT_Value_Count_1() throws Exception { sendObserve("ObserveCancelAll", null); - String expectedId_0 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; - String expectedId_3 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_3; - sendObserve("Observe", expectedId_0); - sendObserve("Observe", expectedId_3); - String actualResult = sendObserve("ObserveCancel", expectedId_0); + String expectedId_3_0_3 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_3; + String expectedId_5_0_3 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_3; + sendObserve("Observe", expectedId_3_0_3); + sendObserve("Observe", expectedId_5_0_3); + String actualResult = sendObserve("ObserveCancel", expectedId_3_0_3); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); assertEquals("1", rpcActualResult.get("value").asText()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java index 4b13c8d757..404bbdc545 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java @@ -30,6 +30,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_1; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_0_0; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_0_3; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_1_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_14; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_9; @@ -181,11 +182,12 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest * ReadComposite {"keys":["batteryLevel", "UtfOffset", "dataRead", "dataWrite"]} */ @Test - public void testReadCompositeSingleResourceByKeys_Result_CONTENT_Value_3_0_IsLwM2mSingleResource_19_0_0_AND_19_0_1_Null() throws Exception { + public void testReadCompositeSingleResourceByKeys_Result_CONTENT_Value_3_0_IsLwM2mSingleResource_19_0_0_AND_19_0_1__IsLwM2mMultipleResource() throws Exception { String expectedKey3_0_9 = RESOURCE_ID_NAME_3_9; String expectedKey3_0_14 = RESOURCE_ID_NAME_3_14; String expectedKey19_0_0 = RESOURCE_ID_NAME_19_0_0; String expectedKey19_1_0 = RESOURCE_ID_NAME_19_1_0; + String expectedKey19_X_0 = "=LwM2mMultipleResource [id=0, values={0=LwM2mResourceInstance [id=0, value=1Bytes, type=OPAQUE]"; String expectedKeys = "[\"" + expectedKey3_0_9 + "\", \"" + expectedKey3_0_14 + "\", \"" + expectedKey19_0_0 + "\", \"" + expectedKey19_1_0 + "\"]"; String actualResult = sendCompositeRPCByKeys(expectedKeys); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); @@ -194,8 +196,8 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest String objectId_19 = pathIdVerToObjectId(objectIdVer_19); String expected3_0_9 = objectInstanceId_3 + "/" + RESOURCE_ID_9 + "=LwM2mSingleResource [id=" + RESOURCE_ID_9 + ", value="; String expected3_0_14 = objectInstanceId_3 + "/" + RESOURCE_ID_14 + "=LwM2mSingleResource [id=" + RESOURCE_ID_14 + ", value="; - String expected19_0_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "=null"; - String expected19_1_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "=null"; + String expected19_0_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + expectedKey19_X_0; + String expected19_1_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + expectedKey19_X_0; String actualValues = rpcActualResult.get("value").asText(); assertTrue(actualValues.contains(expected3_0_9)); assertTrue(actualValues.contains(expected3_0_14)); @@ -203,6 +205,23 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest assertTrue(actualValues.contains(expected19_1_0)); } + /** + * ReadComposite {"keys":["batteryLevel", "UtfOffset", "dataDescription"]} + */ + @Test + public void testReadCompositeSingleResourceByKeys_Result_CONTENT_Value_3_0_IsLwM2mSingleResource_19_0_3_IsNotConfiguredInTheDeviceProfile() throws Exception { + String expectedKey3_0_9 = RESOURCE_ID_NAME_3_9; + String expectedKey3_0_14 = RESOURCE_ID_NAME_3_14; + String expectedKey19_0_3 = RESOURCE_ID_NAME_19_0_3; + String expectedKeys = "[\"" + expectedKey3_0_9 + "\", \"" + expectedKey3_0_14 + "\", \"" + expectedKey19_0_3 + "\"]"; + String actualResult = sendCompositeRPCByKeys(expectedKeys); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); + String actualValue = rpcActualResult.get("error").asText(); + String expectedValue = expectedKey19_0_3 + " is not configured in the device profile!"; + assertEquals(actualValue, expectedValue); + } + private String sendRPCById(String path) throws Exception { String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + path + "\"}}"; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index fa4b601ed0..15ddf062f7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -15,10 +15,12 @@ */ package org.thingsboard.server.transport.lwm2m.security; +import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.ResponseCode; import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; @@ -61,6 +63,7 @@ import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; import static org.eclipse.leshan.client.object.Security.noSecBootstap; +import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; @@ -190,6 +193,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M final Device device = createDevice(deviceCredentials, endpoint); device.getId().getId().toString(); lwM2MTestClient.start(); + Thread.sleep(1000); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) @@ -229,14 +233,18 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M final Device device = createDevice(deviceCredentials, endpoint); String deviceId = device.getId().getId().toString(); lwM2MTestClient.start(); + Thread.sleep(1000); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); Assert.assertEquals(expectedStatusesLwm2m, lwM2MTestClient.getClientStates()); - String executedPath = getObjectIdVer_1() + "/0/" + RESOURCE_ID_9; - sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); + String executedPath = "/" + OBJECT_ID_1 + "_" + lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version + + "/0/" + RESOURCE_ID_9; + String actualResult = sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText()); expectedStatusesBs.add(ON_DEREGISTRATION_STARTED); expectedStatusesBs.add(ON_DEREGISTRATION_SUCCESS); await(awaitAlias) @@ -398,15 +406,4 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M String setRpcRequest = "{\"method\": \"Execute\", \"params\": {\"id\": \"" + path + "\"}}"; return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk()); } - - private String getObjectIdVer_1() { - String ver_Id_0 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version; - String objectIdVer_1; - if ("1.0".equals(ver_Id_0)) { - objectIdVer_1 = "/" + OBJECT_ID_1; - } else { - objectIdVer_1 = "/" + OBJECT_ID_1 + "_" + ver_Id_0; - } - return objectIdVer_1; - } } diff --git a/application/src/test/resources/logback.xml b/application/src/test/resources/logback-test.xml similarity index 100% rename from application/src/test/resources/logback.xml rename to application/src/test/resources/logback-test.xml 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 a4c92de9b1..b7205de7cc 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 @@ -374,14 +374,15 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { } private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { - Lwm2mDeviceProfileTransportConfiguration result = profiles.get(profileId); + + Lwm2mDeviceProfileTransportConfiguration result = profiles != null ? profiles.get(profileId) : null; if (result == null) { log.debug("Fetching profile [{}]", profileId); - DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); + DeviceProfile deviceProfile = deviceProfileCache != null ? deviceProfileCache.get(new DeviceProfileId(profileId)) : null; if (deviceProfile != null) { result = profileUpdate(deviceProfile); } else { - log.info("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); + log.error("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); } } return result; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index 283f1d852c..f193a929e6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -486,9 +486,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl new TbLwM2MLatchCallback<>(latch, new TbLwM2MReadCallback(this, logService, lwM2MClient, versionedId)))); latch.await(); } catch (InterruptedException e) { - log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint()); - } catch (Exception e) { - log.error("[{}] Failed to process read requests!", lwM2MClient.getEndpoint(), e); + log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint(), e); + } catch (Exception e1) { + log.error("[{}] Failed to process read requests!", lwM2MClient.getEndpoint(), e1); logService.log(lwM2MClient, "Failed to process read requests. Possible profile misconfiguration."); } } @@ -504,9 +504,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl latch.await(); } catch (InterruptedException e) { - log.error("[{}] Failed to await Observe requests!", lwM2MClient.getEndpoint()); - } catch (Exception e) { - log.error("[{}] Failed to process observe requests!", lwM2MClient.getEndpoint(), e); + log.error("[{}] Failed to await Observe requests!", lwM2MClient.getEndpoint(), e); + } catch (Exception e1) { + log.error("[{}] Failed to process observe requests!", lwM2MClient.getEndpoint(), e1); logService.log(lwM2MClient, "Failed to process observe requests. Possible profile misconfiguration."); } } From ecc9f8fe3806c5fee0b92998d52f38566faa535c Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 8 Feb 2022 21:38:09 +0200 Subject: [PATCH 13/20] lwm2m: fix bugs in PR commits --- .../lwm2m/bootstrap/LwM2MTransportBootstrapService.java | 4 ++-- .../store/LwM2MBootstrapConfigStoreTaskProvider.java | 2 +- .../transport/lwm2m/server/DefaultLwM2mTransportService.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index fc7893768b..b4572121a5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -72,7 +72,7 @@ public class LwM2MTransportBootstrapService { server.destroy(); log.info("LwM2M transport bootstrap server stopped!"); } catch (Exception e) { - log.error("", e); + log.error("Failed to gracefully stop the LwM2M transport bootstrap server!", e); } } @@ -122,7 +122,7 @@ public class LwM2MTransportBootstrapService { } else { /* by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); - log.info("Unable to load X509 files for BootStrapServer"); + log.info("Unable to load X509 files for BootStrap Server"); dtlsConfig.setAsList(DtlsConfig.DTLS_CIPHER_SUITES, PSK_CIPHER_SUITES); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java index b2b856b807..9100df57a1 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/store/LwM2MBootstrapConfigStoreTaskProvider.java @@ -178,7 +178,7 @@ public class LwM2MBootstrapConfigStoreTaskProvider implements BootstrapTaskProvi serverInstances.put(shortId, instance.getId()); }); } catch (Exception e) { - log.error("", e); + log.error("Failed find Server Instance Id. ", e); } if (this.securityInstances != null && this.securityInstances.size() > 0 && this.serverInstances != null && this.serverInstances.size() > 0) { this.findBootstrapServerId(); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index e8d6ffb7fa..7860fd94a5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -104,7 +104,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { server.destroy(); log.info("LwM2M transport server stopped!"); } catch (Exception e) { - log.error("", e); + log.error("Failed to gracefully stop the LwM2M transport server!", e); } } From b6f317a3b7b8c56a02acfbbfc35e242b6d0f3506 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 9 Feb 2022 18:11:02 +0200 Subject: [PATCH 14/20] lwm2m: fix bugs: init client after connect Lwm2m Server -> awaitClientAfterStartConnectLw() and null pointer exception in getObjectModel --- .../lwm2m/client/LwM2MTestClient.java | 47 +++++++++++++++---- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 5 +- .../AbstractSecurityLwM2MIntegrationTest.java | 14 +++--- .../sql/NoSecLwM2MIntegrationTest.java | 8 ++-- .../security/sql/PskLwm2mIntegrationTest.java | 6 ++- .../security/sql/RpkLwM2MIntegrationTest.java | 6 ++- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 6 ++- .../sql/X509_TrustLwM2MIntegrationTest.java | 6 ++- .../lwm2m/server/client/LwM2mClient.java | 23 +++++++-- .../uplink/DefaultLwM2mUplinkMsgHandler.java | 2 +- 10 files changed, 85 insertions(+), 38 deletions(-) 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 a40922d136..23ae26a0ca 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 @@ -1,12 +1,12 @@ /** * Copyright © 2016-2022 The Thingsboard Authors - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,14 +42,21 @@ import org.eclipse.leshan.core.request.DeregisterRequest; import org.eclipse.leshan.core.request.RegisterRequest; import org.eclipse.leshan.core.request.UpdateRequest; import org.junit.Assert; +import org.mockito.Mockito; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; +import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2mUplinkMsgHandler; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; + import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import static org.awaitility.Awaitility.await; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.eclipse.leshan.core.LwM2mId.DEVICE; @@ -105,9 +112,12 @@ public class LwM2MTestClient { private LwM2mTemperatureSensor lwM2MTemperatureSensor; private LwM2MClientState clientState; private Set clientStates; + private DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; - public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, int shortServerId, int shortServerIdBs, Security securityBs) throws InvalidDDFFileException, IOException { + public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, + int shortServerId, int shortServerIdBs, Security securityBs, DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); + this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; List models = new ArrayList<>(); for (String resourceName : resources) { models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName)); @@ -277,7 +287,7 @@ public class LwM2MTestClient { this.leshanClient.addObserver(observer); if (!isRpc) { - leshanClient.start(); + this.start(true); } } @@ -294,7 +304,7 @@ public class LwM2MTestClient { if (lwm2mServerBs != null) { lwm2mServerBs = null; } - if (lwm2mServer != null) { + if (lwm2mServer != null) { lwm2mServer = null; } if (lwM2MDevice != null) { @@ -314,9 +324,30 @@ public class LwM2MTestClient { } } - public void start() { + public void start(boolean isStartLw) { if (leshanClient != null) { leshanClient.start(); + if (isStartLw) { + this.awaitClientAfterStartConnectLw(); + } + } + } + + private void awaitClientAfterStartConnectLw() { + LwM2mClient lwM2MClient = this.defaultLwM2mUplinkMsgHandlerTest.clientContext.getClientByEndpoint(endpoint); + CountDownLatch latch = new CountDownLatch(1); + Mockito.doAnswer(invocation -> { +// Object result = invocation.callRealMethod(); + latch.countDown(); + return null; + }).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true); + + try { + if (!latch.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("Failed to await TimeOut lwm2m client initialization!"); + } + } catch (InterruptedException e) { + throw new RuntimeException("Exception Failed to await lwm2m client initialization! ", e); } } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index d80b556d72..28fd86a383 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -146,10 +146,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg final Device device = createDevice(deviceCredentials, endpoint); deviceId = device.getId().getId().toString(); - lwM2MTestClient.start(); - - Thread.sleep(1000); - + lwM2MTestClient.start(true); } protected String pathIdVerToObjectId(String pathIdVer) { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index 15ddf062f7..e357b23afe 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -176,7 +176,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M awaitAlias, expectedStatuses, true, - finishState); + finishState, + false); } protected void basicTestConnection(Security security, @@ -187,14 +188,13 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M String awaitAlias, Set expectedStatuses, boolean isBootstrap, - LwM2MClientState finishState) throws Exception { + LwM2MClientState finishState, + boolean isStartLw) throws Exception { createNewClient(security, coapConfig, true, endpoint, isBootstrap, null); createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); device.getId().getId().toString(); - lwM2MTestClient.start(); - Thread.sleep(1000); - + lwM2MTestClient.start(isStartLw); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> finishState.equals(lwM2MTestClient.getClientState())); @@ -232,9 +232,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceId = device.getId().getId().toString(); - lwM2MTestClient.start(); - Thread.sleep(1000); - + lwM2MTestClient.start(true); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java index 345902aa6e..203b1f56c7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java @@ -66,28 +66,28 @@ public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationT } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateTwoSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateTwoSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOTH.name(); String awaitAlias = "await on client state (NoSecBS Trigger Two section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOTH); } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateBootstrapSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateBootstrapSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + BOOTSTRAP_ONLY.name(); String awaitAlias = "await on client state (NoSecBS Trigger Bootstrap section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, BOOTSTRAP_ONLY); } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateLwm2mSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateLwm2mSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + LWM2M_ONLY.name(); String awaitAlias = "await on client state (NoSecBS Trigger Lwm2m section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, LWM2M_ONLY); } @Test - public void testWithNoSecBootstrapRequestTriggerConnectBsSuccess_UpdateNoneSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { + public void testWithNoSecConnectLwm2mSuccessBootstrapRequestTriggerConnectBsSuccess_UpdateNoneSectionAndLm2m_ConnectLwm2mSuccess() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC_BS + "Trigger" + NONE.name(); String awaitAlias = "await on client state (NoSecBS Trigger None section)"; basicTestConnectionBootstrapRequestTriggerBefore(clientEndpoint, awaitAlias, NONE); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index feff1ee926..7eeb4b4090 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -62,7 +62,8 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (Psk_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } @Test @@ -107,6 +108,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (PskBS two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index cfc55fae9a..16c34550c2 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -64,7 +64,8 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (Rpk_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } @Test @@ -124,6 +125,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes "await on client state (RpkBS two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index 6e9dc615e5..57e26c060e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -64,7 +64,8 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg "await on client state (X509_Trust_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } @Test @@ -124,6 +125,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg "await on client state (X509NoTrust two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index 59c7360d20..cd0cec1c16 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -58,7 +58,8 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra "await on client state (X509_Trust_Lwm2m)", expectedStatusesRegistrationLwm2mSuccess, false, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } // Bootstrap + Lwm2m @@ -84,6 +85,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra "await on client state (X509Trust two section)", expectedStatusesRegistrationBsSuccess, true, - ON_REGISTRATION_SUCCESS); + ON_REGISTRATION_SUCCESS, + true); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java index 9b04efa646..f1e4ea1b2c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java @@ -297,11 +297,24 @@ public class LwM2mClient implements Serializable { } public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) { - LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)); - String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); - String verRez = getVerFromPathIdVerOrId(pathIdVer); - return verRez != null && verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) - .getObjectModel(pathIds.getObjectId()) : null; + try { + LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)); + String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); + String verRez = getVerFromPathIdVerOrId(pathIdVer); + return verRez != null && verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration) + .getObjectModel(pathIds.getObjectId()) : null; + } catch (Exception e) { + if (registration == null) { + log.error("Failed Registration is null, GetObjectModelRegistration. ", e); + } + else if (registration.getSupportedObject() == null) { + log.error("Failed SupportedObject in Registration == null, GetObjectModelRegistration.", e); + } + else { + log.error("Failed ModelProvider.getObjectModel [{}] in Registration. ", registration.getSupportedObject(), e); + } + return null; + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index f193a929e6..70863be6eb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -150,7 +150,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl private final LwM2MTelemetryLogService logService; private final LwM2mTransportServerHelper helper; private final TbLwM2MDtlsSessionStore sessionStore; - private final LwM2mClientContext clientContext; + public final LwM2mClientContext clientContext; private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler; private final LwM2mVersionedModelProvider modelProvider; private final RegistrationStore registrationStore; From f704f9bcbc6c74530c644f412ab2f3960f3f27cd Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 9 Feb 2022 18:27:38 +0200 Subject: [PATCH 15/20] lwm2m: fix bugs: init client after connect Lwm2m Server -> awaitClientAfterStartConnectLw() and null pointer exception in getObjectModel (continue) --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) 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 5786cf985d..bbd5a97daa 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 @@ -25,6 +25,8 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.util.SocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; @@ -65,6 +67,7 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataCmd; 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.server.uplink.DefaultLwM2mUplinkMsgHandler; import java.io.IOException; import java.net.ServerSocket; @@ -73,6 +76,7 @@ import java.util.Arrays; import java.util.Base64; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.Executors; @@ -98,6 +102,9 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfil @DaoSqlTest public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { + @Autowired + @SpyBean + DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; // Lwm2m Server public static final int port = 5685; @@ -293,10 +300,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableUdpPort(); - lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); - if (!isRpc) { - Thread.sleep(1000); - } + lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs, this.defaultLwM2mUplinkMsgHandlerTest); } private void clientDestroy() { @@ -306,7 +310,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest awaitClientDestroy(lwM2MTestClient.getLeshanClient()); } } catch (Exception e) { - log.error("", e); + log.error("Failed client Destroy", e); } } @@ -366,7 +370,6 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest .until(() -> isServerPortsAvailable() == null); } - private static String isServerPortsAvailable() { for (int port : SERVERS_PORT_NUMBERS) { try (ServerSocket serverSocket = new ServerSocket(port)) { From a072e9e1af8796c7b5816417d7a3d10b72d21469 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Wed, 9 Feb 2022 19:34:59 +0200 Subject: [PATCH 16/20] lwm2m: Checking licenses... --- .../server/transport/lwm2m/client/LwM2MTestClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 23ae26a0ca..3eb7af8fe4 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 @@ -1,12 +1,12 @@ /** * Copyright © 2016-2022 The Thingsboard Authors - *

+ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. From 28fa1cc6a7844948ebbdbd32f150aa83c2cd98a6 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 10 Feb 2022 08:42:45 +0200 Subject: [PATCH 17/20] lwm2m: Checking licenses... 2 --- .../server/transport/lwm2m/AbstractLwM2MIntegrationTest.java | 1 - 1 file changed, 1 deletion(-) 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 bbd5a97daa..283a02878c 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 @@ -102,7 +102,6 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfil @DaoSqlTest public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest { - @Autowired @SpyBean DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; From 5d839ab75f12f06022a893096c88134599fc9459 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 10 Feb 2022 13:00:59 +0200 Subject: [PATCH 18/20] lwm2m: fix bug of commits --- .../transport/lwm2m/AbstractLwM2MIntegrationTest.java | 7 ++++++- .../server/transport/lwm2m/client/LwM2MTestClient.java | 10 +++++++--- .../lwm2m/server/client/LwM2mClientContextImpl.java | 6 +++--- .../server/uplink/DefaultLwM2mUplinkMsgHandler.java | 10 +++++----- 4 files changed, 21 insertions(+), 12 deletions(-) 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 283a02878c..52c00042df 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 @@ -67,6 +67,7 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataCmd; 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.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2mUplinkMsgHandler; import java.io.IOException; @@ -105,6 +106,9 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest @SpyBean DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; + @Autowired + private LwM2mClientContext clientContextTest; + // Lwm2m Server public static final int port = 5685; public static final int securityPort = 5686; @@ -299,7 +303,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableUdpPort(); - lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs, this.defaultLwM2mUplinkMsgHandlerTest); + lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, + securityBs, this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest); } private void clientDestroy() { 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 3eb7af8fe4..be47847988 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 @@ -44,6 +44,7 @@ import org.eclipse.leshan.core.request.UpdateRequest; import org.junit.Assert; import org.mockito.Mockito; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2mUplinkMsgHandler; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; @@ -113,11 +114,15 @@ public class LwM2MTestClient { private LwM2MClientState clientState; private Set clientStates; private DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; + private LwM2mClientContext clientContext; public void init(Security security, Configuration coapConfig, int port, boolean isRpc, boolean isBootstrap, - int shortServerId, int shortServerIdBs, Security securityBs, DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler) throws InvalidDDFFileException, IOException { + int shortServerId, int shortServerIdBs, Security securityBs, + DefaultLwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, + LwM2mClientContext clientContext) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; + this.clientContext = clientContext; List models = new ArrayList<>(); for (String resourceName : resources) { models.addAll(ObjectLoader.loadDdfFile(LwM2MTestClient.class.getClassLoader().getResourceAsStream("lwm2m/" + resourceName), resourceName)); @@ -334,10 +339,9 @@ public class LwM2MTestClient { } private void awaitClientAfterStartConnectLw() { - LwM2mClient lwM2MClient = this.defaultLwM2mUplinkMsgHandlerTest.clientContext.getClientByEndpoint(endpoint); + LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(endpoint); CountDownLatch latch = new CountDownLatch(1); Mockito.doAnswer(invocation -> { -// Object result = invocation.callRealMethod(); latch.countDown(); return null; }).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true); 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 b7205de7cc..c489c28b31 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 @@ -375,14 +375,14 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { - Lwm2mDeviceProfileTransportConfiguration result = profiles != null ? profiles.get(profileId) : null; + Lwm2mDeviceProfileTransportConfiguration result = profiles.get(profileId); if (result == null) { log.debug("Fetching profile [{}]", profileId); - DeviceProfile deviceProfile = deviceProfileCache != null ? deviceProfileCache.get(new DeviceProfileId(profileId)) : null; + DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); if (deviceProfile != null) { result = profileUpdate(deviceProfile); } else { - log.error("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); + log.warn("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); } } return result; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index 70863be6eb..05ce126c7e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -150,7 +150,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl private final LwM2MTelemetryLogService logService; private final LwM2mTransportServerHelper helper; private final TbLwM2MDtlsSessionStore sessionStore; - public final LwM2mClientContext clientContext; + private final LwM2mClientContext clientContext; private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler; private final LwM2mVersionedModelProvider modelProvider; private final RegistrationStore registrationStore; @@ -487,8 +487,8 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl latch.await(); } catch (InterruptedException e) { log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint(), e); - } catch (Exception e1) { - log.error("[{}] Failed to process read requests!", lwM2MClient.getEndpoint(), e1); + } catch (Exception e) { + log.error("[{}] Failed to process read requests!", lwM2MClient.getEndpoint(), e); logService.log(lwM2MClient, "Failed to process read requests. Possible profile misconfiguration."); } } @@ -505,8 +505,8 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl latch.await(); } catch (InterruptedException e) { log.error("[{}] Failed to await Observe requests!", lwM2MClient.getEndpoint(), e); - } catch (Exception e1) { - log.error("[{}] Failed to process observe requests!", lwM2MClient.getEndpoint(), e1); + } catch (Exception e) { + log.error("[{}] Failed to process observe requests!", lwM2MClient.getEndpoint(), e); logService.log(lwM2MClient, "Failed to process observe requests. Possible profile misconfiguration."); } } From 4140801fb0ce6eac7d34829c9f752f5fe863944c Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 10 Feb 2022 13:07:01 +0200 Subject: [PATCH 19/20] lwm2m: remove import --- .../server/transport/lwm2m/AbstractLwM2MIntegrationTest.java | 1 - .../server/transport/lwm2m/client/LwM2MTestClient.java | 1 - 2 files changed, 2 deletions(-) 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 52c00042df..9f0c18b449 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 @@ -77,7 +77,6 @@ import java.util.Arrays; import java.util.Base64; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.Executors; 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 be47847988..e169705f22 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 @@ -57,7 +57,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import static org.awaitility.Awaitility.await; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.eclipse.leshan.core.LwM2mId.DEVICE; From eac0157984121595c15457f40c8c937aad6e0ea9 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Fri, 11 Feb 2022 12:02:42 +0200 Subject: [PATCH 20/20] lwm2m: Corrections according to comments --- .../transport/lwm2m/server/client/LwM2mClient.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java index f1e4ea1b2c..fddd8ad946 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java @@ -305,13 +305,11 @@ public class LwM2mClient implements Serializable { .getObjectModel(pathIds.getObjectId()) : null; } catch (Exception e) { if (registration == null) { - log.error("Failed Registration is null, GetObjectModelRegistration. ", e); - } - else if (registration.getSupportedObject() == null) { - log.error("Failed SupportedObject in Registration == null, GetObjectModelRegistration.", e); - } - else { - log.error("Failed ModelProvider.getObjectModel [{}] in Registration. ", registration.getSupportedObject(), e); + log.error("[{}] Failed Registration is null, GetObjectModelRegistration. ", this.endpoint, e); + } else if (registration.getSupportedObject() == null) { + log.error("[{}] Failed SupportedObject in Registration, GetObjectModelRegistration.", this.endpoint, e); + } else { + log.error("[{}] Failed ModelProvider.getObjectModel [{}] in Registration. ", this.endpoint, registration.getSupportedObject(), e); } return null; } @@ -436,7 +434,7 @@ public class LwM2mClient implements Serializable { private ContentFormat calculateDefaultContentFormat(Registration registration) { if (registration == null) { return ContentFormat.DEFAULT; - } else{ + } else { return TbLwM2mVersion.fromVersion(registration.getLwM2mVersion()).getContentFormat(); } }