Browse Source

Support DTLS Connection ID with configuration

pull/10063/head
Rhyaldir 3 years ago
parent
commit
4b23a8a96d
  1. 2
      application/src/main/resources/thingsboard.yml
  2. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java
  3. 4
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java
  4. 2
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java
  5. 105
      common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java
  6. 61
      common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfigTest.java
  7. 109
      common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportServiceTest.java
  8. 2
      transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml

2
application/src/main/resources/thingsboard.yml

@ -1044,6 +1044,8 @@ transport:
dtls:
# RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000
retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}"
# "" disables connection id support, 0 enables support but not for incoming traffic, any value greater than 0 set the connection id size in bytes
connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:6}"
server:
# LwM2M Server ID
id: "${LWM2M_SERVER_ID:123}"

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java

@ -38,6 +38,7 @@ import javax.annotation.PreDestroy;
import java.security.cert.X509Certificate;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CURVES_ONLY;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT;
@ -95,6 +96,7 @@ public class LwM2MTransportBootstrapService {
dtlsConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups());
dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers());
dtlsConfig.set(DTLS_RETRANSMISSION_TIMEOUT, serverConfig.getDtlsRetransmissionTimeout(), MILLISECONDS);
dtlsConfig.set(DTLS_CONNECTION_ID_LENGTH, serverConfig.getDtlsConnectionIdLength());
dtlsConfig.set(DTLS_ROLE, SERVER_ONLY);
setServerWithCredentials(builder, dtlsConfig);

4
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java

@ -41,6 +41,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
@Value("${transport.lwm2m.dtls.retransmission_timeout:9000}")
private int dtlsRetransmissionTimeout;
@Getter
@Value("${transport.lwm2m.dtls.connection_id_length:6}")
private Integer dtlsConnectionIdLength;
@Getter
@Value("${transport.lwm2m.timeout:}")
private Long timeout;

2
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java

@ -43,6 +43,7 @@ import javax.annotation.PreDestroy;
import java.security.cert.X509Certificate;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CURVES_ONLY;
import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT;
@ -139,6 +140,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
dtlsConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, config.isRecommendedSupportedGroups());
dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, config.isRecommendedCiphers());
dtlsConfig.set(DTLS_RETRANSMISSION_TIMEOUT, config.getDtlsRetransmissionTimeout(), MILLISECONDS);
dtlsConfig.set(DTLS_CONNECTION_ID_LENGTH, config.getDtlsConnectionIdLength());
dtlsConfig.set(DTLS_ROLE, SERVER_ONLY);
/* Create credentials */

105
common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java

@ -0,0 +1,105 @@
/**
* Copyright © 2016-2024 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.bootstrap;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.leshan.server.californium.LeshanServer;
import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer;
import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.transport.TransportService;
import org.thingsboard.server.transport.lwm2m.bootstrap.secure.TbLwM2MDtlsBootstrapCertificateVerifier;
import org.thingsboard.server.transport.lwm2m.bootstrap.store.LwM2MBootstrapSecurityStore;
import org.thingsboard.server.transport.lwm2m.bootstrap.store.LwM2MInMemoryBootstrapConfigStore;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier;
import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.when;
@ExtendWith(MockitoExtension.class)
public class LwM2MTransportBootstrapServiceTest {
@Mock
private LwM2MTransportServerConfig serverConfig;
@Mock
private LwM2MTransportBootstrapConfig bootstrapConfig;
@Mock
private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore;
@Mock
private LwM2MInMemoryBootstrapConfigStore lwM2MInMemoryBootstrapConfigStore;
@Mock
private TransportService transportService;
@Mock
private TbLwM2MDtlsBootstrapCertificateVerifier certificateVerifier;
@Test
public void getLHServer_creates_ConnectionIdGenerator_when_connection_id_length_not_null(){
final Integer CONNECTION_ID_LENGTH = 6;
when(serverConfig.getDtlsConnectionIdLength()).thenReturn(CONNECTION_ID_LENGTH);
var lwM2MBootstrapService = createLwM2MBootstrapService();
var server = lwM2MBootstrapService.getLhBootstrapServer();
var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint");
assertThat(securedEndpoint).isNotNull();
var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config");
assertThat(config).isNotNull();
assertThat(config.getConnectionIdGenerator()).isNotNull();
assertThat((Integer) ReflectionTestUtils.getField(config.getConnectionIdGenerator(), "connectionIdLength"))
.isEqualTo(CONNECTION_ID_LENGTH);
}
@Test
public void getLHServer_creates_no_ConnectionIdGenerator_when_connection_id_length_is_null(){
when(serverConfig.getDtlsConnectionIdLength()).thenReturn(null);
var lwM2MBootstrapService = createLwM2MBootstrapService();
var server = lwM2MBootstrapService.getLhBootstrapServer();
var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint");
assertThat(securedEndpoint).isNotNull();
var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config");
assertThat(config).isNotNull();
assertThat(config.getConnectionIdGenerator()).isNull();
}
private LwM2MTransportBootstrapService createLwM2MBootstrapService() {
setDefaultConfigVariables();
return new LwM2MTransportBootstrapService(serverConfig, bootstrapConfig, lwM2MBootstrapSecurityStore,
lwM2MInMemoryBootstrapConfigStore, transportService, certificateVerifier);
}
private void setDefaultConfigVariables(){
when(bootstrapConfig.getPort()).thenReturn(5683);
when(bootstrapConfig.getSecurePort()).thenReturn(5684);
when(serverConfig.isRecommendedCiphers()).thenReturn(false);
when(serverConfig.getDtlsRetransmissionTimeout()).thenReturn(9000);
}
}

61
common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfigTest.java

@ -0,0 +1,61 @@
/**
* Copyright © 2016-2024 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.config;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(value = LwM2MTransportServerConfig.class)
@ContextConfiguration(classes = {LwM2MTransportServerConfig.class}, loader = SpringBootContextLoader.class)
@TestPropertySource(properties = {
"transport.sessions.report_timeout=10",
"transport.lwm2m.security.recommended_ciphers=true",
"transport.lwm2m.security.recommended_supported_groups=true",
"transport.lwm2m.downlink_pool_size=10",
"transport.lwm2m.uplink_pool_size=10",
"transport.lwm2m.ota_pool_size=10",
"transport.lwm2m.clean_period_in_sec=2",
"transport.lwm2m.dtls.connection_id_length="
})
class LwM2MTransportServerConfigTest {
@MockBean(name = "lwm2mServerCredentials")
private SslCredentialsConfig credentialsConfig;
@MockBean(name = "lwm2mTrustCredentials")
private SslCredentialsConfig trustCredentialsConfig;
@Autowired
private LwM2MTransportServerConfig serverConfig;
@Test
void getDtlsConnectionIdLength_return_null_is_property_is_empty() {
// note: transport.lwm2m.dtls.connect_id_length is set in TestPropertySource
assertThat(serverConfig.getDtlsConnectionIdLength()).isNull();
}
}

109
common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportServiceTest.java

@ -0,0 +1,109 @@
/**
* Copyright © 2016-2024 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.server;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.leshan.server.californium.LeshanServer;
import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier;
import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.when;
@ExtendWith(MockitoExtension.class)
public class DefaultLwM2mTransportServiceTest {
@Mock
private LwM2mTransportContext context;
@Mock
private LwM2MTransportServerConfig config;
@Mock
private OtaPackageDataCache otaPackageDataCache;
@Mock
private LwM2mUplinkMsgHandler handler;
@Mock
private CaliforniumRegistrationStore registrationStore;
@Mock
private TbSecurityStore securityStore;
@Mock
private TbLwM2MDtlsCertificateVerifier certificateVerifier;
@Mock
private TbLwM2MAuthorizer authorizer;
@Mock
private LwM2mVersionedModelProvider modelProvider;
@Test
public void getLHServer_creates_ConnectionIdGenerator_when_connection_id_length_not_null(){
final Integer CONNECTION_ID_LENGTH = 6;
when(config.getDtlsConnectionIdLength()).thenReturn(CONNECTION_ID_LENGTH);
var lwm2mService = createLwM2MService();
LeshanServer server = ReflectionTestUtils.invokeMethod(lwm2mService, "getLhServer");
assertThat(server).isNotNull();
var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint");
assertThat(securedEndpoint).isNotNull();
var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config");
assertThat(config).isNotNull();
assertThat(config.getConnectionIdGenerator()).isNotNull();
assertThat((Integer) ReflectionTestUtils.getField(config.getConnectionIdGenerator(), "connectionIdLength"))
.isEqualTo(CONNECTION_ID_LENGTH);
}
@Test
public void getLHServer_creates_no_ConnectionIdGenerator_when_connection_id_length_is_null(){
when(config.getDtlsConnectionIdLength()).thenReturn(null);
var lwm2mService = createLwM2MService();
LeshanServer server = ReflectionTestUtils.invokeMethod(lwm2mService, "getLhServer");
assertThat(server).isNotNull();
var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint");
assertThat(securedEndpoint).isNotNull();
var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config");
assertThat(config).isNotNull();
assertThat(config.getConnectionIdGenerator()).isNull();
}
private DefaultLwM2mTransportService createLwM2MService() {
setDefaultConfigVariables();
return new DefaultLwM2mTransportService(context, config, otaPackageDataCache, handler, registrationStore,
securityStore, certificateVerifier, authorizer, modelProvider);
}
private void setDefaultConfigVariables(){
when(config.getPort()).thenReturn(5683);
when(config.getSecurePort()).thenReturn(5684);
when(config.isRecommendedCiphers()).thenReturn(false);
when(config.getDtlsRetransmissionTimeout()).thenReturn(9000);
}
}

2
transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml

@ -155,6 +155,8 @@ transport:
dtls:
# RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000
retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}"
# "" disables connection id support, 0 enables support but not for incoming traffic, any value greater than 0 set the connection id size in bytes
connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:6}"
server:
# LwM2M Server ID
id: "${LWM2M_SERVER_ID:123}"

Loading…
Cancel
Save