lwm2m: fix bug security tests

This commit is contained in:
nickAS21 2022-01-28 12:45:05 +02:00
parent c3081c45cf
commit cad54fa70c
7 changed files with 42 additions and 218 deletions

View File

@ -15,83 +15,20 @@
*/ */
package org.thingsboard.server.controller; 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 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.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.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.SpringBootContextLoader;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; 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.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner; 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.URI;
import java.net.URISyntaxException; 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") @ActiveProfiles("test")
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)

View File

@ -74,10 +74,11 @@ import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; 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.noSec;
import static org.eclipse.leshan.client.object.Security.noSecBootstap; import static org.eclipse.leshan.client.object.Security.noSecBootstap;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 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_STARTED;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; 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 SECURE_URI = COAPS + host + ":" + securityPort;
public static final String URI_BS = COAP + hostBs + ":" + portBs; public static final String URI_BS = COAP + hostBs + ":" + portBs;
public static final String SECURE_URI_BS = COAPS + hostBs + ":" + securityPortBs; 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 = noSec(URI, shortServerId);
public static final Security SECURITY_NO_SEC_BS = noSecBootstap(URI_BS); public static final Security SECURITY_NO_SEC_BS = noSecBootstap(URI_BS);
@ -148,121 +150,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest
" \"clientOnlyObserveAfterConnect\": 1\n" + " \"clientOnlyObserveAfterConnect\": 1\n" +
" }"; " }";
protected final Set<Lwm2mTestHelper.LwM2MClientState> expectedStatusesBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS));
protected final String TRANSPORT_CONFIGURATION_NO_SEC_WITHOUT_ATTRIBUTES = "{\n" + protected final Set<Lwm2mTestHelper.LwM2MClientState> expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS));
" \"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<Lwm2mTestHelper.LwM2MClientState> expectedStatusesBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS));
protected final Set<Lwm2mTestHelper.LwM2MClientState> expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS));
protected final Set<Lwm2mTestHelper.LwM2MClientState> expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected final Set<Lwm2mTestHelper.LwM2MClientState> expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS));
protected DeviceProfile deviceProfile; protected DeviceProfile deviceProfile;
protected ScheduledExecutorService executor; protected ScheduledExecutorService executor;
@ -299,6 +188,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest
@After @After
public void after() { public void after() {
wsClient.close();
clientDestroy(); clientDestroy();
executor.shutdownNow(); executor.shutdownNow();
} }

View File

@ -20,9 +20,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.eclipse.californium.elements.config.Configuration; import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.client.object.Security;
import org.eclipse.leshan.core.CertificateUsage;
import org.eclipse.leshan.core.ResponseCode; import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.core.SecurityMode;
import org.eclipse.leshan.core.util.Hex; import org.eclipse.leshan.core.util.Hex;
import org.junit.Assert; import org.junit.Assert;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
@ -173,7 +171,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint));
this.basicTestConnection(noSecBootstap(URI_BS), this.basicTestConnection(noSecBootstap(URI_BS),
deviceCredentials, deviceCredentials,
COAP_CONFIG, COAP_CONFIG_BS,
clientEndpoint, clientEndpoint,
transportConfiguration, transportConfiguration,
awaitAlias, awaitAlias,
@ -183,14 +181,14 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
} }
protected void basicTestConnection(Security security, protected void basicTestConnection(Security security,
LwM2MDeviceCredentials deviceCredentials, LwM2MDeviceCredentials deviceCredentials,
Configuration coapConfig, Configuration coapConfig,
String endpoint, String endpoint,
Lwm2mDeviceProfileTransportConfiguration transportConfiguration, Lwm2mDeviceProfileTransportConfiguration transportConfiguration,
String awaitAlias, String awaitAlias,
Set<LwM2MClientState> expectedStatuses, Set<LwM2MClientState> expectedStatuses,
boolean isBootstrap, boolean isBootstrap,
LwM2MClientState finishState) throws Exception { LwM2MClientState finishState) throws Exception {
createNewClient(security, coapConfig, true, endpoint, isBootstrap, null); createNewClient(security, coapConfig, true, endpoint, isBootstrap, null);
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
final Device device = createDevice(deviceCredentials, endpoint); 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 { public void basicTestConnectionBootstrapRequestTriggerBefore(String clientEndpoint, String awaitAlias, LwM2MProfileBootstrapConfigType type) throws Exception {
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type)); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsNoSec(type));
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint));
this.basicTestConnectionBootstrapRequestTrigger( this.basicTestConnectionBootstrapRequestTrigger(
SECURITY_NO_SEC, SECURITY_NO_SEC,
deviceCredentials, deviceCredentials,
COAP_CONFIG, COAP_CONFIG,
clientEndpoint, clientEndpoint,
transportConfiguration, transportConfiguration,
awaitAlias, awaitAlias,
expectedStatusesRegistrationLwm2mSuccess, expectedStatusesRegistrationLwm2mSuccess,
expectedStatusesRegistrationBsSuccess, expectedStatusesRegistrationBsSuccess,
false, false,
SECURITY_NO_SEC_BS); SECURITY_NO_SEC_BS);
} }
private void basicTestConnectionBootstrapRequestTrigger(Security security, private void basicTestConnectionBootstrapRequestTrigger(Security security,
LwM2MDeviceCredentials deviceCredentials, LwM2MDeviceCredentials deviceCredentials,
Configuration coapConfig, Configuration coapConfig,
String endpoint, String endpoint,
Lwm2mDeviceProfileTransportConfiguration transportConfiguration, Lwm2mDeviceProfileTransportConfiguration transportConfiguration,
String awaitAlias, String awaitAlias,
Set<LwM2MClientState> expectedStatusesLwm2m, Set<LwM2MClientState> expectedStatusesLwm2m,
Set<LwM2MClientState> expectedStatusesBs, Set<LwM2MClientState> expectedStatusesBs,
boolean isBootstrap, boolean isBootstrap,
Security securityBs) throws Exception { Security securityBs) throws Exception {
createNewClient(security, coapConfig, true, endpoint, isBootstrap, securityBs); createNewClient(security, coapConfig, true, endpoint, isBootstrap, securityBs);
createDeviceProfile(transportConfiguration); createDeviceProfile(transportConfiguration);
final Device device = createDevice(deviceCredentials, endpoint); final Device device = createDevice(deviceCredentials, endpoint);

View File

@ -101,7 +101,7 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false);
this.basicTestConnection(securityBs, this.basicTestConnection(securityBs,
deviceCredentials, deviceCredentials,
COAP_CONFIG, COAP_CONFIG_BS,
clientEndpoint, clientEndpoint,
transportConfiguration, transportConfiguration,
"await on client state (PskBS two section)", "await on client state (PskBS two section)",

View File

@ -118,7 +118,7 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK, false); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK, false);
this.basicTestConnection(securityBs, this.basicTestConnection(securityBs,
deviceCredentials, deviceCredentials,
COAP_CONFIG, COAP_CONFIG_BS,
clientEndpoint, clientEndpoint,
transportConfiguration, transportConfiguration,
"await on client state (RpkBS two section)", "await on client state (RpkBS two section)",

View File

@ -118,7 +118,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false);
this.basicTestConnection(security, this.basicTestConnection(security,
deviceCredentials, deviceCredentials,
COAP_CONFIG, COAP_CONFIG_BS,
clientEndpoint, clientEndpoint,
transportConfiguration, transportConfiguration,
"await on client state (X509NoTrust two section)", "await on client state (X509NoTrust two section)",

View File

@ -78,7 +78,7 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, false);
this.basicTestConnection(security, this.basicTestConnection(security,
deviceCredentials, deviceCredentials,
COAP_CONFIG, COAP_CONFIG_BS,
clientEndpoint, clientEndpoint,
transportConfiguration, transportConfiguration,
"await on client state (X509Trust two section)", "await on client state (X509Trust two section)",