From b864680b812e86ecc6d1ba032256768fa05ab3fa Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 11 Feb 2021 23:39:38 +0200 Subject: [PATCH] Lwm2m: back: start DTLS -one server 4 security --- .../service/lwm2m/LwM2MModelsRepository.java | 37 +- .../src/main/resources/thingsboard.yml | 32 +- ...TransportBootstrapServerConfiguration.java | 295 +++++++------- ...2MTransportBootstrapServerInitializer.java | 26 +- .../LwM2MTransportServerConfiguration.java | 365 ++++++++---------- .../LwM2MTransportServerInitializer.java | 57 +-- .../lwm2m/LwM2MTransportConfigBootstrap.java | 40 +- .../lwm2m/LwM2MTransportConfigServer.java | 50 +-- .../src/main/resources/tb-lwm2m-transport.yml | 37 +- .../device/lwm2m/profile-config.models.ts | 2 +- 10 files changed, 358 insertions(+), 583 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java index ce6a781d19..5057893d5c 100644 --- a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java @@ -217,23 +217,19 @@ public class LwM2MModelsRepository { switch (mode) { case NO_SEC: bsServ.setHost(contextBootStrap.getBootstrapHost()); - bsServ.setPort(contextBootStrap.getBootstrapPortNoSecPsk()); + bsServ.setPort(contextBootStrap.getBootstrapPortNoSec()); bsServ.setServerPublicKey(""); break; case PSK: - bsServ.setHost(contextBootStrap.getBootstrapSecureHost()); - bsServ.setPort(contextBootStrap.getBootstrapSecurePortPsk()); + bsServ.setHost(contextBootStrap.getBootstrapHostSecurity()); + bsServ.setPort(contextBootStrap.getBootstrapPortSecurity()); bsServ.setServerPublicKey(""); break; case RPK: - bsServ.setHost(contextBootStrap.getBootstrapSecureHost()); - bsServ.setPort(contextBootStrap.getBootstrapSecurePortRpk()); - bsServ.setServerPublicKey(getRPKPublicKey(this.contextBootStrap.getBootstrapPublicX(), this.contextBootStrap.getBootstrapPublicY())); - break; case X509: - bsServ.setHost(contextBootStrap.getBootstrapSecureHost()); - bsServ.setPort(contextBootStrap.getBootstrapSecurePortX509()); - bsServ.setServerPublicKey(getServerPublicKeyX509(contextBootStrap.getBootstrapAlias())); + bsServ.setHost(contextBootStrap.getBootstrapHostSecurity()); + bsServ.setPort(contextBootStrap.getBootstrapPortSecurity()); + bsServ.setServerPublicKey(getPublicKey (contextBootStrap.getBootstrapAlias(), this.contextBootStrap.getBootstrapPublicX(), this.contextBootStrap.getBootstrapPublicY())); break; default: break; @@ -243,23 +239,19 @@ public class LwM2MModelsRepository { switch (mode) { case NO_SEC: bsServ.setHost(contextServer.getServerHost()); - bsServ.setPort(contextServer.getServerPortNoSecPsk()); + bsServ.setPort(contextServer.getServerPortNoSec()); bsServ.setServerPublicKey(""); break; case PSK: - bsServ.setHost(contextServer.getServerSecureHost()); - bsServ.setPort(contextServer.getServerPortPsk()); + bsServ.setHost(contextServer.getServerHostSecurity()); + bsServ.setPort(contextServer.getServerPortSecurity()); bsServ.setServerPublicKey(""); break; case RPK: - bsServ.setHost(contextServer.getServerSecureHost()); - bsServ.setPort(contextServer.getServerPortRpk()); - bsServ.setServerPublicKey(getRPKPublicKey(this.contextServer.getServerPublicX(), this.contextServer.getServerPublicY())); - break; case X509: - bsServ.setHost(contextServer.getServerSecureHost()); - bsServ.setPort(contextServer.getServerPortX509()); - bsServ.setServerPublicKey(getServerPublicKeyX509(contextServer.getServerAlias())); + bsServ.setHost(contextServer.getServerHostSecurity()); + bsServ.setPort(contextServer.getServerPortSecurity()); + bsServ.setServerPublicKey(getPublicKey (contextServer.getServerAlias(), this.contextServer.getServerPublicX(), this.contextServer.getServerPublicY())); break; default: break; @@ -268,6 +260,11 @@ public class LwM2MModelsRepository { return bsServ; } + private String getPublicKey (String alias, String publicServerX, String publicServerY) { + String publicKey = getServerPublicKeyX509(alias); + return publicKey != null ? publicKey : getRPKPublicKey(publicServerX, publicServerY); + } + /** * @param alias * @return PublicKey format HexString or null diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 9ec4029c8a..f90f35a42b 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -584,7 +584,7 @@ transport: update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" secure: - # Only Certificate_x509: + # Certificate_x509: # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}" @@ -597,18 +597,11 @@ transport: server: id: "${LWM2M_SERVER_ID:123}" bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" - bind_port_no_sec_psk: "${LWM2M_BIND_PORT_NO_SEC_PSK:5685}" - bind_port_no_sec_rpk: "${LWM2M_BIND_PORT_NO_SEC_RPK:5687}" - bind_port_no_sec_x509: "${LWM2M_BIND_PORT_NO_SEC_X509:5689}" + bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC:5685}" secure: - bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" - start_psk: "${START_SERVER_PSK:true}" - start_rpk: "${START_SERVER_RPK:true}" - start_x509: "${START_SERVER_X509:true}" - bind_port_psk: "${LWM2M_BIND_PORT_SEC_PSK:5686}" - bind_port_rpk: "${LWM2M_BIND_PORT_SEC_RPK:5688}" - bind_port_x509: "${LWM2M_BIND_PORT_SEC_X509:5690}" - # Only RPK: Public & Private Key + bind_address_security: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" + bind_port_security: "${LWM2M_BIND_PORT_SECURITY:5686}" + # Only for RPK: Public & Private Key. If the keystore file is missing or not working # create_rpk: "${CREATE_RPK:}" public_x: "${LWM2M_SERVER_PUBLIC_X:405354ea8893471d9296afbc8b020a5c6201b0bb25812a53b849d4480fa5f069}" public_y: "${LWM2M_SERVER_PUBLIC_Y:30c9237e946a3a1692c1cafaa01a238a077f632c99371348337512363f28212b}" @@ -619,18 +612,11 @@ transport: enable: "${LWM2M_BOOTSTRAP_ENABLED:true}" id: "${LWM2M_SERVER_ID:111}" bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" - bind_port_no_sec_psk: "${LWM2M_BIND_PORT_NO_SEC_BS:5691}" - bind_port_no_sec_rpk: "${LWM2M_BIND_PORT_NO_SEC_BS:5693}" - bind_port_no_sec_x509: "${LWM2M_BIND_PORT_NO_SEC_BS:5695}" + bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC_BS:5687}" secure: - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" - start_psk: "${START_SERVER_PSK_BS:true}" - start_rpk: "${START_SERVER_RPK_BS:true}" - start_x509: "${START_SERVER_X509_BS:true}" - bind_port_psk: "${LWM2M_BIND_PORT_SEC_PSK_BS:5692}" - bind_port_rpk: "${LWM2M_BIND_PORT_SER_RPK_BS:5694}" - bind_port_x509: "${LWM2M_BIND_PORT_SEC_X509_BS:5696}" - # Only RPK: Public & Private Key + bind_address_security: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" + bind_port_security: "${LWM2M_BIND_PORT_SEC_BS:5688}" + # Only for RPK: Public & Private Key. If the keystore file is missing or not working public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}" public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}" private_s: "${LWM2M_SERVER_PRIVATE_S_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}" diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java index ed7d1d9da1..ecc8e7c83e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerConfiguration.java @@ -25,20 +25,18 @@ import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServerBuil import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapSecurityStore; import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MInMemoryBootstrapConfigStore; import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBootstrapSessionManager; -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; import org.thingsboard.server.transport.lwm2m.server.LwM2MTransportContextServer; import java.math.BigInteger; import java.security.AlgorithmParameters; -import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; @@ -49,14 +47,13 @@ import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.Arrays; +import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.PSK; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RPK; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509; import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig; @Slf4j @@ -78,61 +75,42 @@ public class LwM2MTransportBootstrapServerConfiguration { @Autowired private LwM2MInMemoryBootstrapConfigStore lwM2MInMemoryBootstrapConfigStore; - @Primary - @Bean(name = "leshanBootstrapX509") - @ConditionalOnExpression("('${transport.lwm2m.bootstrap.secure.start_x509:false}'=='true')") - public LeshanBootstrapServer getLeshanBootstrapServerX509() { - log.info("Prepare and start BootstrapServerX509... PostConstruct"); - return getLeshanBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPortNoSecX509(), this.contextBs.getCtxBootStrap().getBootstrapSecurePortX509(), X509); - } - - @Bean(name = "leshanBootstrapPsk") - @ConditionalOnExpression("('${transport.lwm2m.bootstrap.secure.start_psk:false}'=='true')") - public LeshanBootstrapServer getLeshanBootstrapServerPsk() { - log.info("Prepare and start BootstrapServerRsk... PostConstruct"); - return getLeshanBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPortNoSecPsk(), this.contextBs.getCtxBootStrap().getBootstrapSecurePortPsk(), PSK); - } - @Bean(name = "leshanBootstrapRpk") - @ConditionalOnExpression("('${transport.lwm2m.bootstrap.secure.start_rpk:false}'=='true')") - public LeshanBootstrapServer getLeshanBootstrapServerRpk() { - log.info("Prepare and start BootstrapServerRpk... PostConstruct"); - return getLeshanBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPortNoSecRpk(), this.contextBs.getCtxBootStrap().getBootstrapSecurePortRpk(), RPK); + @Bean + public LeshanBootstrapServer getLeshanBootstrapServer() { + log.info("Prepare and start BootstrapServer... PostConstruct"); + return this.getLhBootstrapServer(this.contextBs.getCtxBootStrap().getBootstrapPortNoSec(), this.contextBs.getCtxBootStrap().getBootstrapPortSecurity()); } - public LeshanBootstrapServer getLeshanBootstrapServer(Integer bootstrapPortNoSec, Integer bootstrapSecurePort, LwM2MSecurityMode dtlsMode) { + public LeshanBootstrapServer getLhBootstrapServer(Integer bootstrapPortNoSec, Integer bootstrapSecurePort) { LeshanBootstrapServerBuilder builder = new LeshanBootstrapServerBuilder(); builder.setLocalAddress(this.contextBs.getCtxBootStrap().getBootstrapHost(), bootstrapPortNoSec); - builder.setLocalSecureAddress(this.contextBs.getCtxBootStrap().getBootstrapSecureHost(), bootstrapSecurePort); + builder.setLocalSecureAddress(this.contextBs.getCtxBootStrap().getBootstrapHostSecurity(), bootstrapSecurePort); /** Create CoAP Config */ - builder.setCoapConfig(getCoapConfig (bootstrapPortNoSec, bootstrapSecurePort)); + builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); + + /** Define model provider (Create Models )*/ + builder.setModel(new StaticModel(contextS.getCtxServer().getModelsValue())); + + /** Create credentials */ + this.setServerWithCredentials(builder); - /** ConfigStore */ + /** Set securityStore with new ConfigStore */ builder.setConfigStore(lwM2MInMemoryBootstrapConfigStore); /** SecurityStore */ builder.setSecurityStore(lwM2MBootstrapSecurityStore); - /** Define model provider (Create Models )*/ - builder.setModel(new StaticModel(contextS.getCtxServer().getModelsValue())); - - /** Create credentials */ - LwM2MSetSecurityStoreBootstrap(builder, dtlsMode); /** Create and Set DTLS Config */ DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); - if (dtlsMode==PSK) { - dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getCtxServer().isRecommendedCiphers()); - dtlsConfig.setRecommendedSupportedGroupsOnly(this.contextS.getCtxServer().isRecommendedSupportedGroups()); - dtlsConfig.setSupportedCipherSuites(TLS_PSK_WITH_AES_128_CBC_SHA256); - } - else { - dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getCtxServer().isRecommendedCiphers()); -// dtlsConfig.setRecommendedSupportedGroupsOnly(false); - } - builder.setDtlsConfig(dtlsConfig); + dtlsConfig.setRecommendedSupportedGroupsOnly(!this.contextS.getCtxServer().isRecommendedSupportedGroups()); + dtlsConfig.setRecommendedCipherSuitesOnly(this.contextS.getCtxServer().isRecommendedCiphers()); + dtlsConfig.setSupportedCipherSuites(TLS_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256); + /** Set DTLS Config */ + builder.setDtlsConfig(dtlsConfig); BootstrapSessionManager sessionManager = new LwM2mDefaultBootstrapSessionManager(lwM2MBootstrapSecurityStore); builder.setSessionManager(sessionManager); @@ -141,150 +119,153 @@ public class LwM2MTransportBootstrapServerConfiguration { return builder.build(); } - public void LwM2MSetSecurityStoreBootstrap(LeshanBootstrapServerBuilder builder, LwM2MSecurityMode dtlsMode) { - - /** Set securityStore with new registrationStore */ - - switch (dtlsMode) { - /** Use No_Sec only */ - case NO_SEC: - setServerWithX509Cert(builder, NO_SEC.code); - break; - /** Use PSK/RPK */ - case PSK: - break; - case RPK: - setRPK(builder); - break; - case X509: - setServerWithX509Cert(builder, X509.code); - break; - /** Use X509_EST only */ - case X509_EST: - // TODO support sentinel pool and make pool configurable - break; - /** Use ather X509, PSK, No_Sec ?? */ - default: - break; - } - } - - private void setRPK(LeshanBootstrapServerBuilder builder) { - try { - /** Get Elliptic Curve Parameter spec for secp256r1 */ - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); - algoParameters.init(new ECGenParameterSpec("secp256r1")); - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); - if (this.contextBs.getCtxBootStrap().getBootstrapPublicX() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicX().isEmpty() && this.contextBs.getCtxBootStrap().getBootstrapPublicY() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicY().isEmpty()) { - /** Get point values */ - byte[] publicX = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicX().toCharArray()); - byte[] publicY = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicY().toCharArray()); - /** Create key specs */ - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), - parameterSpec); - /** Get keys */ - this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); - } - if (this.contextBs.getCtxBootStrap().getBootstrapPrivateS() != null && !this.contextBs.getCtxBootStrap().getBootstrapPrivateS().isEmpty()) { - /** Get point values */ - byte[] privateS = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPrivateS().toCharArray()); - /** Create key specs */ - KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); - /** Get keys */ - this.privateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); - } - if (this.publicKey != null && this.publicKey.getEncoded().length > 0 && - this.privateKey != null && this.privateKey.getEncoded().length > 0) { - builder.setPublicKey(this.publicKey); - builder.setPrivateKey(this.privateKey); - this.contextBs.getCtxBootStrap().setBootstrapPublicKey(this.publicKey); - getParamsRPK(); - } - } catch (GeneralSecurityException | IllegalArgumentException e) { - log.error("[{}] Failed generate Server PSK/RPK", e.getMessage()); - throw new RuntimeException(e); - } - } - - private void setServerWithX509Cert(LeshanBootstrapServerBuilder builder, int securityModeCode) { + private void setServerWithCredentials(LeshanBootstrapServerBuilder builder) { try { if (this.contextS.getCtxServer().getKeyStoreValue() != null) { KeyStore keyStoreServer = this.contextS.getCtxServer().getKeyStoreValue(); - setBuilderX509(builder); - X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getCtxServer().getRootAlias()); - if (rootCAX509Cert != null && securityModeCode == X509.code) { - X509Certificate[] trustedCertificates = new X509Certificate[1]; - trustedCertificates[0] = rootCAX509Cert; - builder.setTrustedCertificates(trustedCertificates); + if (this.setBuilderX509(builder)) { + X509Certificate rootCAX509Cert = (X509Certificate) keyStoreServer.getCertificate(this.contextS.getCtxServer().getRootAlias()); + if (rootCAX509Cert != null) { + X509Certificate[] trustedCertificates = new X509Certificate[1]; + trustedCertificates[0] = rootCAX509Cert; + builder.setTrustedCertificates(trustedCertificates); + } else { + /** by default trust all */ + builder.setTrustedCertificates(new X509Certificate[0]); + } + } else if (this.setServerRPK(builder)) { + this.infoParamsServerRPK(); } else { /** by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); + log.info("Unable to load X509 files for BootStrapServer"); + this.infoParamsServerPSK(); } } - else { - /** by default trust all */ - builder.setTrustedCertificates(new X509Certificate[0]); - log.error("Unable to load X509 files for BootStrapServer"); - } } catch (KeyStoreException ex) { log.error("[{}] Unable to load X509 files server", ex.getMessage()); } - } - private void setBuilderX509(LeshanBootstrapServerBuilder builder) { + private boolean setBuilderX509(LeshanBootstrapServerBuilder builder) { /** * For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks */ try { X509Certificate serverCertificate = (X509Certificate) this.contextS.getCtxServer().getKeyStoreValue().getCertificate(this.contextBs.getCtxBootStrap().getBootstrapAlias()); - this.privateKey = (PrivateKey) this.contextS.getCtxServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getCtxServer().getKeyStorePasswordServer() == null ? null : this.contextS.getCtxServer().getKeyStorePasswordServer().toCharArray()); - if (this.privateKey != null && this.privateKey.getEncoded().length > 0) { - builder.setPrivateKey(this.privateKey); - } - if (serverCertificate != null) { + PrivateKey privateKey = (PrivateKey) this.contextS.getCtxServer().getKeyStoreValue().getKey(this.contextBs.getCtxBootStrap().getBootstrapAlias(), this.contextS.getCtxServer().getKeyStorePasswordServer() == null ? null : this.contextS.getCtxServer().getKeyStorePasswordServer().toCharArray()); + PublicKey publicKey = serverCertificate.getPublicKey(); + if (serverCertificate != null && + privateKey != null && privateKey.getEncoded().length > 0 && + publicKey != null && publicKey.getEncoded().length > 0) { + builder.setPublicKey(serverCertificate.getPublicKey()); + builder.setPrivateKey(privateKey); builder.setCertificateChain(new X509Certificate[]{serverCertificate}); - this.infoParamsX509(serverCertificate); + this.infoParamsServerX509(serverCertificate, publicKey, privateKey); + return true; + } else { + return false; } } catch (Exception ex) { log.error("[{}] Unable to load KeyStore files server", ex.getMessage()); + return false; } } - private void getParamsRPK() { - if (this.publicKey instanceof ECPublicKey) { - /** Get x coordinate */ - byte[] x = ((ECPublicKey) this.publicKey).getW().getAffineX().toByteArray(); - if (x[0] == 0) - x = Arrays.copyOfRange(x, 1, x.length); - - /** Get Y coordinate */ - byte[] y = ((ECPublicKey) this.publicKey).getW().getAffineY().toByteArray(); - if (y[0] == 0) - y = Arrays.copyOfRange(y, 1, y.length); - - /** Get Curves params */ - String params = ((ECPublicKey) this.publicKey).getParams().toString(); - log.info( - " \nBootstrap uses RPK : \n Elliptic Curve parameters : [{}] \n Public x coord : [{}] \n Public y coord : [{}] \n Public Key (Hex): [{}] \n Private Key (Hex): [{}]", - params, Hex.encodeHexString(x), Hex.encodeHexString(y), - Hex.encodeHexString(this.publicKey.getEncoded()), - Hex.encodeHexString(this.privateKey.getEncoded())); - } else { - throw new IllegalStateException("Unsupported Public Key Format (only ECPublicKey supported)."); - } - } - - private void infoParamsX509(X509Certificate certificate) { + private void infoParamsServerX509(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) { try { - log.info("BootStrap uses X509 : \n X509 Certificate (Hex): [{}] \n Private Key (Hex): [{}]", + log.info("Bootstrap Server uses X509 : \n X509 Certificate (Hex): [{}] \n Public Key (Hex): [{}] \n Private Key (Hex): [{}]", Hex.encodeHexString(certificate.getEncoded()), - Hex.encodeHexString(this.privateKey.getEncoded())); + Hex.encodeHexString(publicKey.getEncoded()), + Hex.encodeHexString(privateKey.getEncoded())); } catch (CertificateEncodingException e) { log.error("", e); } } + private boolean setServerRPK(LeshanBootstrapServerBuilder builder) { + try { + this.generateKeyForBootstrapRPK(); + if (this.publicKey != null && this.publicKey.getEncoded().length > 0 && + this.privateKey != null && this.privateKey.getEncoded().length > 0) { + builder.setPublicKey(this.publicKey); + builder.setPrivateKey(this.privateKey); + return true; + } + } catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) { + log.error("Fail create Bootstrap Server with RPK", e); + } + return false; + } + + + /** + * From yml^ bootstrap + * public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}" + * public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}" + * private_s: "${LWM2M_SERVER_PRIVATE_S_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}" + */ + private void generateKeyForBootstrapRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { + /** Get Elliptic Curve Parameter spec for secp256r1 */ + AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); + algoParameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); + if (this.contextBs.getCtxBootStrap().getBootstrapPublicX() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicX().isEmpty() && this.contextBs.getCtxBootStrap().getBootstrapPublicY() != null && !this.contextBs.getCtxBootStrap().getBootstrapPublicY().isEmpty()) { + /** Get point values */ + byte[] publicX = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicX().toCharArray()); + byte[] publicY = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPublicY().toCharArray()); + /** Create key specs */ + KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), + parameterSpec); + /** Get keys */ + this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); + } + if (this.contextBs.getCtxBootStrap().getBootstrapPrivateS() != null && !this.contextBs.getCtxBootStrap().getBootstrapPrivateS().isEmpty()) { + /** Get point values */ + byte[] privateS = Hex.decodeHex(this.contextBs.getCtxBootStrap().getBootstrapPrivateS().toCharArray()); + /** Create key specs */ + KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); + /** Get keys */ + this.privateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); + } + } + + private void infoParamsServerRPK() { + /** Get x coordinate */ + byte[] x = ((ECPublicKey) this.publicKey).getW().getAffineX().toByteArray(); + if (x[0] == 0) + x = Arrays.copyOfRange(x, 1, x.length); + + /** Get Y coordinate */ + byte[] y = ((ECPublicKey) this.publicKey).getW().getAffineY().toByteArray(); + if (y[0] == 0) + y = Arrays.copyOfRange(y, 1, y.length); + + /** Get Curves params */ + String params = ((ECPublicKey) this.publicKey).getParams().toString(); + String privHex = Hex.encodeHexString(this.privateKey.getEncoded()); + log.info("Server uses RPK -> serverNoSecureURI : [{}], serverSecureURI : [{}], \n" + + "Public Key (Hex): [{}] \n" + + "Private Key (Hex): [{}], \n" + + "- public_x : [{}] \n" + + "- public_y : [{}] \n" + + "- private_s : [{}] \n" + + "- Elliptic Curve parameters : [{}]", + this.contextBs.getCtxBootStrap().getBootstrapHost() + ":" + this.contextBs.getCtxBootStrap().getBootstrapPortNoSec(), + this.contextBs.getCtxBootStrap().getBootstrapHostSecurity() + ":" + this.contextBs.getCtxBootStrap().getBootstrapPortSecurity(), + Hex.encodeHexString(this.publicKey.getEncoded()), + Hex.encodeHexString(this.privateKey.getEncoded()), + Hex.encodeHexString(x), + Hex.encodeHexString(y), + privHex.substring(privHex.length() - 64), + params); + } + + private void infoParamsServerPSK() { + log.info("Server uses PSK -> serverNoSecureURI : [{}], serverSecureURI : [{}]", + this.contextBs.getCtxBootStrap().getBootstrapHost() + ":" + this.contextBs.getCtxBootStrap().getBootstrapPortNoSec(), + this.contextBs.getCtxBootStrap().getBootstrapHostSecurity() + ":" + this.contextBs.getCtxBootStrap().getBootstrapPortSecurity()); + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerInitializer.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerInitializer.java index 6ca751b138..c3d6d9d0c1 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerInitializer.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServerInitializer.java @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.bootstrap; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; @@ -31,39 +30,20 @@ import javax.annotation.PreDestroy; public class LwM2MTransportBootstrapServerInitializer { @Autowired(required = false) - @Qualifier("leshanBootstrapX509") - private LeshanBootstrapServer lhBServerCert; - - @Autowired(required = false) - @Qualifier("leshanBootstrapPsk") - private LeshanBootstrapServer lhBServerPsk; - - @Autowired(required = false) - @Qualifier("leshanBootstrapRpk") - private LeshanBootstrapServer lhBServerRpk; + private LeshanBootstrapServer lhBServer; @Autowired private LwM2MTransportContextBootstrap contextBS; @PostConstruct public void init() { - if (this.contextBS.getCtxBootStrap().getBootstrapStartPsk()) { - this.lhBServerPsk.start(); - } - if (this.contextBS.getCtxBootStrap().getBootstrapStartRpk()) { - this.lhBServerRpk.start(); - } - if (this.contextBS.getCtxBootStrap().getBootstrapStartX509()) { - this.lhBServerCert.start(); - } + this.lhBServer.start(); } @PreDestroy public void shutdown() throws InterruptedException { log.info("Stopping LwM2M transport Bootstrap Server!"); - lhBServerPsk.destroy(); - lhBServerRpk.destroy(); - lhBServerCert.destroy(); + lhBServer.destroy(); log.info("LwM2M transport Bootstrap Server stopped!"); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java index 388138d8c3..48ff2adc51 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerConfiguration.java @@ -25,31 +25,20 @@ import org.eclipse.leshan.server.californium.LeshanServer; import org.eclipse.leshan.server.californium.LeshanServerBuilder; import org.eclipse.leshan.server.model.LwM2mModelProvider; import org.eclipse.leshan.server.model.VersionedModelProvider; -import org.eclipse.leshan.server.redis.RedisRegistrationStore; -import org.eclipse.leshan.server.redis.RedisSecurityStore; import org.eclipse.leshan.server.security.DefaultAuthorizer; -import org.eclipse.leshan.server.security.EditableSecurityStore; import org.eclipse.leshan.server.security.SecurityChecker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; +import org.springframework.stereotype.Component; import org.thingsboard.server.transport.lwm2m.server.secure.LwM2mInMemorySecurityStore; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.util.Pool; import java.math.BigInteger; -import java.net.URI; -import java.net.URISyntaxException; import java.security.AlgorithmParameters; -import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; @@ -60,20 +49,17 @@ import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.Arrays; +import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.PSK; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.RPK; -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.X509; import static org.thingsboard.server.transport.lwm2m.server.LwM2MTransportHandler.getCoapConfig; - @Slf4j -@ComponentScan("org.thingsboard.server.transport.lwm2m.server") -@ComponentScan("org.thingsboard.server.transport.lwm2m.utils") -@Configuration("LwM2MTransportServerConfiguration") +@Component("LwM2MTransportServerConfiguration") @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") public class LwM2MTransportServerConfiguration { private PublicKey publicKey; @@ -85,32 +71,16 @@ public class LwM2MTransportServerConfiguration { @Autowired private LwM2mInMemorySecurityStore lwM2mInMemorySecurityStore; - @Primary - @Bean(name = "leshanServerPsk") - @ConditionalOnExpression("('${transport.lwm2m.server.secure.start_psk:false}'=='true')") - public LeshanServer getLeshanServerPsk() { - log.info("Starting LwM2M transport ServerPsk... PostConstruct"); - return getLeshanServer(this.context.getCtxServer().getServerPortNoSecPsk(), this.context.getCtxServer().getServerPortPsk(), PSK); - } - - @Bean(name = "leshanServerRpk") - @ConditionalOnExpression("('${transport.lwm2m.server.secure.start_rpk:false}'=='true')") - public LeshanServer getLeshanServerRpk() { - log.info("Starting LwM2M transport ServerRpk... PostConstruct"); - return getLeshanServer(this.context.getCtxServer().getServerPortNoSecRpk(), this.context.getCtxServer().getServerPortRpk(), RPK); - } - - @Bean(name = "leshanServerX509") - @ConditionalOnExpression("('${transport.lwm2m.server.secure.start_x509:false}'=='true')") - public LeshanServer getLeshanServerX509() { - log.info("Starting LwM2M transport ServerX509... PostConstruct"); - return getLeshanServer(this.context.getCtxServer().getServerPortNoSecX509(), this.context.getCtxServer().getServerPortX509(), X509); + @Bean + public LeshanServer getLeshanServer() { + log.info("Starting LwM2M transport Server... PostConstruct"); + return this.getLhServer(this.context.getCtxServer().getServerPortNoSec(), this.context.getCtxServer().getServerPortSecurity()); } - private LeshanServer getLeshanServer(Integer serverPortNoSec, Integer serverSecurePort, LwM2MSecurityMode dtlsMode) { + private LeshanServer getLhServer(Integer serverPortNoSec, Integer serverSecurePort) { LeshanServerBuilder builder = new LeshanServerBuilder(); builder.setLocalAddress(this.context.getCtxServer().getServerHost(), serverPortNoSec); - builder.setLocalSecureAddress(this.context.getCtxServer().getServerSecureHost(), serverSecurePort); + builder.setLocalSecureAddress(this.context.getCtxServer().getServerHostSecurity(), serverSecurePort); builder.setEncoder(new DefaultLwM2mNodeEncoder()); LwM2mNodeDecoder decoder = new DefaultLwM2mNodeDecoder(); builder.setDecoder(decoder); @@ -123,22 +93,19 @@ public class LwM2MTransportServerConfiguration { LwM2mModelProvider modelProvider = new VersionedModelProvider(this.context.getCtxServer().getModelsValue()); builder.setObjectModelProvider(modelProvider); - /** Create DTLS security mode - * There can be only one DTLS security mode - */ - this.LwM2MSetSecurityStoreServer(builder, dtlsMode); + /** Create credentials */ + this.setServerWithCredentials(builder); + + /** Set securityStore with new registrationStore */ + builder.setSecurityStore(lwM2mInMemorySecurityStore); + /** Create DTLS Config */ DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); - if (dtlsMode==PSK) { - dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getCtxServer().isRecommendedCiphers()); - dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getCtxServer().isRecommendedSupportedGroups()); - dtlsConfig.setSupportedCipherSuites(TLS_PSK_WITH_AES_128_CBC_SHA256); - } - else { - dtlsConfig.setRecommendedSupportedGroupsOnly(!this.context.getCtxServer().isRecommendedSupportedGroups()); - dtlsConfig.setRecommendedCipherSuitesOnly(!this.context.getCtxServer().isRecommendedCiphers()); - } + dtlsConfig.setRecommendedSupportedGroupsOnly(!this.context.getCtxServer().isRecommendedSupportedGroups()); + dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getCtxServer().isRecommendedCiphers()); + dtlsConfig.setSupportedCipherSuites(TLS_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256); + /** Set DTLS Config */ builder.setDtlsConfig(dtlsConfig); @@ -150,154 +117,42 @@ public class LwM2MTransportServerConfiguration { return builder.build(); } - private void LwM2MSetSecurityStoreServer(LeshanServerBuilder builder, LwM2MSecurityMode dtlsMode) { - /** Set securityStore with new registrationStore */ - EditableSecurityStore securityStore = lwM2mInMemorySecurityStore; - switch (dtlsMode) { - /** Use PSK only */ - case PSK: - generatePSK_RPK(); - infoParamsPSK(); - break; - /** Use RPK only */ - case RPK: - generatePSK_RPK(); - if (this.publicKey != null && this.publicKey.getEncoded().length > 0 && - this.privateKey != null && this.privateKey.getEncoded().length > 0) { - builder.setPublicKey(this.publicKey); - builder.setPrivateKey(this.privateKey); - infoParamsRPK(); - } - break; - /** Use x509 only */ - case X509: - setServerWithX509Cert(builder); - break; - /** No security */ - case NO_SEC: - builder.setTrustedCertificates(new X509Certificate[0]); - break; - /** Use x509 with EST */ - case X509_EST: - // TODO support sentinel pool and make pool configurable - break; - case REDIS: - /** - * Set securityStore with new registrationStore (if use redis store) - * Connect to redis - */ - Pool jedis = null; - try { - jedis = new JedisPool(new URI(this.context.getCtxServer().getRedisUrl())); - securityStore = new RedisSecurityStore(jedis); - builder.setRegistrationStore(new RedisRegistrationStore(jedis)); - } catch (URISyntaxException e) { - log.error("", e); - } - break; - default: - } - - /** Set securityStore with registrationStore (if x509)*/ - if (dtlsMode == X509) { - builder.setAuthorizer(new DefaultAuthorizer(securityStore, new SecurityChecker() { - @Override - protected boolean matchX509Identity(String endpoint, String receivedX509CommonName, - String expectedX509CommonName) { - return endpoint.startsWith(expectedX509CommonName); - } - })); - } - - /** Set securityStore with new registrationStore */ - builder.setSecurityStore(securityStore); - } - - private void generatePSK_RPK() { - try { - /** Get Elliptic Curve Parameter spec for secp256r1 */ - AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); - algoParameters.init(new ECGenParameterSpec("secp256r1")); - ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); - if (this.context.getCtxServer().getServerPublicX() != null && !this.context.getCtxServer().getServerPublicX().isEmpty() && this.context.getCtxServer().getServerPublicY() != null && !this.context.getCtxServer().getServerPublicY().isEmpty()) { - /** Get point values */ - byte[] publicX = Hex.decodeHex(this.context.getCtxServer().getServerPublicX().toCharArray()); - byte[] publicY = Hex.decodeHex(this.context.getCtxServer().getServerPublicY().toCharArray()); - /** Create key specs */ - KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), - parameterSpec); - /** Get keys */ - this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); - } - if (this.context.getCtxServer().getServerPrivateS() != null && !this.context.getCtxServer().getServerPrivateS().isEmpty()) { - /** Get point values */ - byte[] privateS = Hex.decodeHex(this.context.getCtxServer().getServerPrivateS().toCharArray()); - /** Create key specs */ - KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); - /** Get keys */ - this.privateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); - } - } catch (GeneralSecurityException | IllegalArgumentException e) { - log.error("[{}] Failed generate Server PSK/RPK", e.getMessage()); - throw new RuntimeException(e); - } - } - - private void infoParamsPSK() { - log.info("\nServer uses PSK -> private key : \n security key : [{}] \n serverSecureURI : [{}]", - Hex.encodeHexString(this.privateKey.getEncoded()), - this.context.getCtxServer().getServerSecureHost() + ":" + Integer.toString(this.context.getCtxServer().getServerPortPsk())); - } - - private void infoParamsRPK() { - if (this.publicKey instanceof ECPublicKey) { - /** Get x coordinate */ - byte[] x = ((ECPublicKey) this.publicKey).getW().getAffineX().toByteArray(); - if (x[0] == 0) - x = Arrays.copyOfRange(x, 1, x.length); - - /** Get Y coordinate */ - byte[] y = ((ECPublicKey) this.publicKey).getW().getAffineY().toByteArray(); - if (y[0] == 0) - y = Arrays.copyOfRange(y, 1, y.length); - - /** Get Curves params */ - String params = ((ECPublicKey) this.publicKey).getParams().toString(); - log.info( - " \nServer uses RPK : \n Elliptic Curve parameters : [{}] \n Public x coord : [{}] \n Public y coord : [{}] \n Public Key (Hex): [{}] \n Private Key (Hex): [{}]", - params, Hex.encodeHexString(x), Hex.encodeHexString(y), - Hex.encodeHexString(this.publicKey.getEncoded()), - Hex.encodeHexString(this.privateKey.getEncoded())); - } else { - throw new IllegalStateException("Unsupported Public Key Format (only ECPublicKey supported)."); - } - } - - - private void setServerWithX509Cert(LeshanServerBuilder builder) { + private void setServerWithCredentials(LeshanServerBuilder builder) { try { if (this.context.getCtxServer().getKeyStoreValue() != null) { - setBuilderX509(builder); - X509Certificate rootCAX509Cert = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getRootAlias()); - if (rootCAX509Cert != null) { - X509Certificate[] trustedCertificates = new X509Certificate[1]; - trustedCertificates[0] = rootCAX509Cert; - builder.setTrustedCertificates(trustedCertificates); + if (this.setBuilderX509(builder)) { + X509Certificate rootCAX509Cert = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getRootAlias()); + if (rootCAX509Cert != null) { + X509Certificate[] trustedCertificates = new X509Certificate[1]; + trustedCertificates[0] = rootCAX509Cert; + builder.setTrustedCertificates(trustedCertificates); + } else { + /** by default trust all */ + builder.setTrustedCertificates(new X509Certificate[0]); + } + /** Set securityStore with registrationStore*/ + builder.setAuthorizer(new DefaultAuthorizer(lwM2mInMemorySecurityStore, new SecurityChecker() { + @Override + protected boolean matchX509Identity(String endpoint, String receivedX509CommonName, + String expectedX509CommonName) { + return endpoint.startsWith(expectedX509CommonName); + } + })); + } else if (this.setServerRPK(builder)) { + this.infoParamsServerRPK(); } else { /** by default trust all */ builder.setTrustedCertificates(new X509Certificate[0]); + log.info("Unable to load X509 files for LWM2MServer"); + this.infoParamsServerPSK(); } - } else { - /** by default trust all */ - builder.setTrustedCertificates(new X509Certificate[0]); - log.error("Unable to load X509 files for LWM2MServer"); } } catch (KeyStoreException ex) { log.error("[{}] Unable to load X509 files server", ex.getMessage()); } } - private void setBuilderX509(LeshanServerBuilder builder) { + private boolean setBuilderX509(LeshanServerBuilder builder) { /** * For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks @@ -305,38 +160,122 @@ public class LwM2MTransportServerConfiguration { try { X509Certificate serverCertificate = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getServerAlias()); PrivateKey privateKey = (PrivateKey) this.context.getCtxServer().getKeyStoreValue().getKey(this.context.getCtxServer().getServerAlias(), this.context.getCtxServer().getKeyStorePasswordServer() == null ? null : this.context.getCtxServer().getKeyStorePasswordServer().toCharArray()); - builder.setPrivateKey(privateKey); - builder.setCertificateChain(new X509Certificate[]{serverCertificate}); - this.infoParamsX509(serverCertificate, privateKey); + PublicKey publicKey = serverCertificate.getPublicKey(); + if (serverCertificate != null && + privateKey != null && privateKey.getEncoded().length > 0 && + publicKey != null && publicKey.getEncoded().length > 0) { + builder.setPublicKey(serverCertificate.getPublicKey()); + builder.setPrivateKey(privateKey); + builder.setCertificateChain(new X509Certificate[]{serverCertificate}); + this.infoParamsServerX509(serverCertificate, publicKey, privateKey); + return true; + } + else { + return false; + } } catch (Exception ex) { log.error("[{}] Unable to load KeyStore files server", ex.getMessage()); + return false; } -// /** -// * For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE -// * For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks -// */ -// try { -// X509Certificate serverCertificate = (X509Certificate) this.context.getCtxServer().getKeyStoreValue().getCertificate(this.context.getCtxServer().getServerPrivateS()); -// this.privateKey = (PrivateKey) this.context.getCtxServer().getKeyStoreValue().getKey(this.context.getCtxServer().getServerAlias(), this.context.getCtxServer().getKeyStorePasswordServer() == null ? null : this.context.getCtxServer().getKeyStorePasswordServer().toCharArray()); -// if (this.privateKey != null && this.privateKey.getEncoded().length > 0) { -// builder.setPrivateKey(this.privateKey); -// } -// if (serverCertificate != null) { -// builder.setCertificateChain(new X509Certificate[]{serverCertificate}); -// this.infoParamsX509(serverCertificate); -// } -// } catch (Exception ex) { -// log.error("[{}] Unable to load KeyStore files server", ex.getMessage()); -// } } - private void infoParamsX509(X509Certificate certificate, PrivateKey privateKey) { + private void infoParamsServerX509(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) { try { - log.info("Server uses X509 : \n X509 Certificate (Hex): [{}] \n Private Key (Hex): [{}]", + log.info("Server uses X509 : \n X509 Certificate (Hex): [{}] \n Public Key (Hex): [{}] \n Private Key (Hex): [{}]", Hex.encodeHexString(certificate.getEncoded()), + Hex.encodeHexString(publicKey.getEncoded()), Hex.encodeHexString(privateKey.getEncoded())); } catch (CertificateEncodingException e) { log.error("", e); } } + + private boolean setServerRPK(LeshanServerBuilder builder) { + try { + this.generateKeyForRPK(); + if (this.publicKey != null && this.publicKey.getEncoded().length > 0 && + this.privateKey != null && this.privateKey.getEncoded().length > 0) { + builder.setPublicKey(this.publicKey); + builder.setPrivateKey(this.privateKey); + return true; + } + } catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) { + log.error("Fail create Server with RPK", e); + } + return false; + } + + + /** + * From yml^ server + * public_x: "${LWM2M_SERVER_PUBLIC_X:405354ea8893471d9296afbc8b020a5c6201b0bb25812a53b849d4480fa5f069}" + * public_y: "${LWM2M_SERVER_PUBLIC_Y:30c9237e946a3a1692c1cafaa01a238a077f632c99371348337512363f28212b}" + * private_s: "${LWM2M_SERVER_PRIVATE_S:274671fe40ce937b8a6352cf0a418e8a39e4bf0bb9bf74c910db953c20c73802}" + */ + private void generateKeyForRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException { + /** Get Elliptic Curve Parameter spec for secp256r1 */ + AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); + algoParameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); + if (this.context.getCtxServer().getServerPublicX() != null && + !this.context.getCtxServer().getServerPublicX().isEmpty() && + this.context.getCtxServer().getServerPublicY() != null && + !this.context.getCtxServer().getServerPublicY().isEmpty()) { + /** Get point values */ + byte[] publicX = Hex.decodeHex(this.context.getCtxServer().getServerPublicX().toCharArray()); + byte[] publicY = Hex.decodeHex(this.context.getCtxServer().getServerPublicY().toCharArray()); + /** Create key specs */ + KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)), + parameterSpec); + /** Get keys */ + this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); + } + if (this.context.getCtxServer().getServerPrivateS() != null && + !this.context.getCtxServer().getServerPrivateS().isEmpty()) { + /** Get point values */ + byte[] privateS = Hex.decodeHex(this.context.getCtxServer().getServerPrivateS().toCharArray()); + /** Create key specs */ + KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); + /** Get keys */ + this.privateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); + } + } + + private void infoParamsServerRPK() { + /** Get x coordinate */ + byte[] x = ((ECPublicKey) this.publicKey).getW().getAffineX().toByteArray(); + if (x[0] == 0) + x = Arrays.copyOfRange(x, 1, x.length); + + /** Get Y coordinate */ + byte[] y = ((ECPublicKey) this.publicKey).getW().getAffineY().toByteArray(); + if (y[0] == 0) + y = Arrays.copyOfRange(y, 1, y.length); + + /** Get Curves params */ + String params = ((ECPublicKey) this.publicKey).getParams().toString(); + String privHex = Hex.encodeHexString(this.privateKey.getEncoded()); + log.info("Server uses RPK -> serverNoSecureURI : [{}], serverSecureURI : [{}], \n" + + "Public Key (Hex): [{}] \n" + + "Private Key (Hex): [{}], \n" + + "- public_x : [{}] \n" + + "- public_y : [{}] \n" + + "- private_s : [{}] \n" + + "- Elliptic Curve parameters : [{}]", + this.context.getCtxServer().getServerHost() + ":" + this.context.getCtxServer().getServerPortNoSec(), + this.context.getCtxServer().getServerHostSecurity() + ":" + this.context.getCtxServer().getServerPortSecurity(), + Hex.encodeHexString(this.publicKey.getEncoded()), + Hex.encodeHexString(this.privateKey.getEncoded()), + Hex.encodeHexString(x), + Hex.encodeHexString(y), + privHex.substring(privHex.length() - 64), + params); + } + + private void infoParamsServerPSK() { + log.info("Server uses PSK -> serverNoSecureURI : [{}], serverSecureURI : [{}]", + this.context.getCtxServer().getServerHost() + ":" + Integer.toString(this.context.getCtxServer().getServerPortNoSec()), + this.context.getCtxServer().getServerHostSecurity() + ":" + Integer.toString(this.context.getCtxServer().getServerPortSecurity())); + } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java index 90215326b4..b62287a845 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2MTransportServerInitializer.java @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.server; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.server.californium.LeshanServer; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC; @@ -31,69 +30,35 @@ import javax.annotation.PreDestroy; @ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") public class LwM2MTransportServerInitializer { - @Autowired private LwM2MTransportServiceImpl service; @Autowired(required = false) - @Qualifier("leshanServerX509") - private LeshanServer lhServerX509; - - @Autowired(required = false) - @Qualifier("leshanServerPsk") - private LeshanServer lhServerPsk; - - @Autowired(required = false) - @Qualifier("leshanServerRpk") - private LeshanServer lhServerRpk; + private LeshanServer leshanServer; @Autowired private LwM2MTransportContextServer context; @PostConstruct public void init() { - if (this.context.getCtxServer().getEnableGenPskRpk()) new LWM2MGenerationPSkRPkECC(); - if (this.context.getCtxServer().isServerStartPsk()) { - this.startLhServerPsk(); - } - if (this.context.getCtxServer().isServerStartRpk()) { - this.startLhServerRpk(); + if (this.context.getCtxServer().getEnableGenPskRpk()) { + new LWM2MGenerationPSkRPkECC(); } - if (this.context.getCtxServer().isServerStartX509()) { - this.startLhServerX509(); - } - } - - private void startLhServerPsk() { - this.lhServerPsk.start(); - LwM2mServerListener lhServerPskListener = new LwM2mServerListener(this.lhServerPsk, service); - this.lhServerPsk.getRegistrationService().addListener(lhServerPskListener.registrationListener); - this.lhServerPsk.getPresenceService().addListener(lhServerPskListener.presenceListener); - this.lhServerPsk.getObservationService().addListener(lhServerPskListener.observationListener); - } - - private void startLhServerRpk() { - this.lhServerRpk.start(); - LwM2mServerListener lhServerRpkListener = new LwM2mServerListener(this.lhServerRpk, service); - this.lhServerRpk.getRegistrationService().addListener(lhServerRpkListener.registrationListener); - this.lhServerRpk.getPresenceService().addListener(lhServerRpkListener.presenceListener); - this.lhServerRpk.getObservationService().addListener(lhServerRpkListener.observationListener); + this.startLhServer(); } - private void startLhServerX509() { - this.lhServerX509.start(); - LwM2mServerListener lhServerCertListener = new LwM2mServerListener(this.lhServerX509, service); - this.lhServerX509.getRegistrationService().addListener(lhServerCertListener.registrationListener); - this.lhServerX509.getPresenceService().addListener(lhServerCertListener.presenceListener); - this.lhServerX509.getObservationService().addListener(lhServerCertListener.observationListener); + private void startLhServer() { + this.leshanServer.start(); + LwM2mServerListener lhServerCertListener = new LwM2mServerListener(this.leshanServer, service); + this.leshanServer.getRegistrationService().addListener(lhServerCertListener.registrationListener); + this.leshanServer.getPresenceService().addListener(lhServerCertListener.presenceListener); + this.leshanServer.getObservationService().addListener(lhServerCertListener.observationListener); } @PreDestroy public void shutdown() { log.info("Stopping LwM2M transport Server!"); - lhServerPsk.destroy(); - lhServerRpk.destroy(); - lhServerX509.destroy(); + leshanServer.destroy(); log.info("LwM2M transport Server stopped!"); } } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigBootstrap.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigBootstrap.java index 48f31edc97..d946694305 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigBootstrap.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigBootstrap.java @@ -39,49 +39,21 @@ public class LwM2MTransportConfigBootstrap { @Value("${transport.lwm2m.bootstrap.id:}") private Integer bootstrapServerId; - @Getter - @Value("${transport.lwm2m.bootstrap.secure.start_psk:}") - private Boolean bootstrapStartPsk; - - @Getter - @Value("${transport.lwm2m.bootstrap.secure.start_rpk:}") - private Boolean bootstrapStartRpk; - - @Getter - @Value("${transport.lwm2m.bootstrap.secure.start_x509:}") - private Boolean bootstrapStartX509; - @Getter @Value("${transport.lwm2m.bootstrap.bind_address:}") private String bootstrapHost; @Getter - @Value("${transport.lwm2m.bootstrap.secure.bind_address:}") - private String bootstrapSecureHost; - - @Getter - @Value("${transport.lwm2m.bootstrap.bind_port_no_sec_psk:}") - private Integer bootstrapPortNoSecPsk; - - @Getter - @Value("${transport.lwm2m.bootstrap.bind_port_no_sec_rpk:}") - private Integer bootstrapPortNoSecRpk; - - @Getter - @Value("${transport.lwm2m.bootstrap.bind_port_no_sec_x509:}") - private Integer bootstrapPortNoSecX509; - - @Getter - @Value("${transport.lwm2m.bootstrap.secure.bind_port_psk:}") - private Integer bootstrapSecurePortPsk; + @Value("${transport.lwm2m.bootstrap.bind_port_no_sec:}") + private Integer bootstrapPortNoSec; @Getter - @Value("${transport.lwm2m.bootstrap.secure.bind_port_rpk:}") - private Integer bootstrapSecurePortRpk; + @Value("${transport.lwm2m.bootstrap.secure.bind_address_security:}") + private String bootstrapHostSecurity; @Getter - @Value("${transport.lwm2m.bootstrap.secure.bind_port_x509:}") - private Integer bootstrapSecurePortX509; + @Value("${transport.lwm2m.bootstrap.secure.bind_port_security:}") + private Integer bootstrapPortSecurity; @Getter @Value("${transport.lwm2m.bootstrap.secure.public_x:}") diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java index dfe2b75fef..9894cb79ea 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/lwm2m/LwM2MTransportConfigServer.java @@ -79,7 +79,7 @@ public class LwM2MTransportConfigServer { private String BASE_DIR_PATH = System.getProperty("user.dir"); @Getter -// private String PATH_DATA_MICROSERVICE = "/usr/share/tb-lwm2m-transport/data$"; + // private String PATH_DATA_MICROSERVICE = "/usr/share/tb-lwm2m-transport/data$"; private String PATH_DATA = "data"; @Getter @@ -146,58 +146,29 @@ public class LwM2MTransportConfigServer { @Value("${transport.lwm2m.secure.root_alias:}") private String rootAlias; - @Getter - @Value("${transport.lwm2m.server.secure.start_psk:}") - private boolean serverStartPsk; - - @Getter - @Value("${transport.lwm2m.server.secure.start_rpk:}") - private boolean serverStartRpk; - - @Getter - @Value("${transport.lwm2m.server.secure.start_x509:}") - private boolean serverStartX509; - @Getter @Value("${transport.lwm2m.secure.enable_gen_psk_rpk:}") private Boolean enableGenPskRpk; - @Getter - @Value("${transport.lwm2m.server.bind_address:}") - private String serverHost; - @Getter @Value("${transport.lwm2m.server.id:}") private Integer serverId; @Getter - @Value("${transport.lwm2m.server.secure.bind_address:}") - private String serverSecureHost; - - - @Getter - @Value("${transport.lwm2m.server.bind_port_no_sec_psk:}") - private Integer serverPortNoSecPsk; - - @Getter - @Value("${transport.lwm2m.server.bind_port_no_sec_rpk:}") - private Integer serverPortNoSecRpk; - - @Getter - @Value("${transport.lwm2m.server.bind_port_no_sec_x509:}") - private Integer serverPortNoSecX509; + @Value("${transport.lwm2m.server.bind_address:}") + private String serverHost; @Getter - @Value("${transport.lwm2m.server.secure.bind_port_psk:}") - private Integer serverPortPsk; + @Value("${transport.lwm2m.server.secure.bind_address_security:}") + private String serverHostSecurity; @Getter - @Value("${transport.lwm2m.server.secure.bind_port_rpk:}") - private Integer serverPortRpk; + @Value("${transport.lwm2m.server.bind_port_no_sec:}") + private Integer serverPortNoSec; @Getter - @Value("${transport.lwm2m.server.secure.bind_port_x509:}") - private Integer serverPortX509; + @Value("${transport.lwm2m.server.secure.bind_port_security:}") + private Integer serverPortSecurity; @Getter @Value("${transport.lwm2m.server.secure.public_x:}") @@ -303,7 +274,4 @@ public class LwM2MTransportConfigServer { ResourceModel resource = this.getResourceModel(registration, pathIds); return (resource == null) ? ResourceModel.Operations.NONE : resource.operations; } - - - } diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 700b428906..ee06cf9a93 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -60,7 +60,7 @@ transport: update_registered_pool_size: "${LWM2M_UPDATE_REGISTERED_POOL_SIZE:10}" un_registered_pool_size: "${LWM2M_UN_REGISTERED_POOL_SIZE:10}" secure: - # Only Certificate_x509: + # Certificate_x509: # To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format # Create new X509 Certificates: common/transport/lwm2m/src/main/resources/credentials/shell/lwM2M_credentials.sh key_store_type: "${LWM2M_KEYSTORE_TYPE:JKS}" @@ -73,18 +73,11 @@ transport: server: id: "${LWM2M_SERVER_ID:123}" bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" - bind_port_no_sec_psk: "${LWM2M_BIND_PORT_NO_SEC_PSK:5685}" - bind_port_no_sec_rpk: "${LWM2M_BIND_PORT_NO_SEC_RPK:5687}" - bind_port_no_sec_x509: "${LWM2M_BIND_PORT_NO_SEC_X509:5689}" + bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC:5685}" secure: - bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" - start_psk: "${START_SERVER_PSK:true}" - start_rpk: "${START_SERVER_RPK:true}" - start_x509: "${START_SERVER_X509:true}" - bind_port_psk: "${LWM2M_BIND_PORT_SEC_PSK:5686}" - bind_port_rpk: "${LWM2M_BIND_PORT_SEC_RPK:5688}" - bind_port_x509: "${LWM2M_BIND_PORT_SEC_X509:5690}" - # Only RPK: Public & Private Key + bind_address_security: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" + bind_port_security: "${LWM2M_BIND_PORT_SECURITY:5686}" + # Only for RPK: Public & Private Key. If the keystore file is missing or not working # create_rpk: "${CREATE_RPK:}" public_x: "${LWM2M_SERVER_PUBLIC_X:405354ea8893471d9296afbc8b020a5c6201b0bb25812a53b849d4480fa5f069}" public_y: "${LWM2M_SERVER_PUBLIC_Y:30c9237e946a3a1692c1cafaa01a238a077f632c99371348337512363f28212b}" @@ -92,28 +85,22 @@ transport: # Only Certificate_x509: alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}" bootstrap: - enable: "${BOOTSTRAP:true}" + enable: "${LWM2M_BOOTSTRAP_ENABLED:true}" id: "${LWM2M_SERVER_ID:111}" bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" - bind_port_no_sec_psk: "${LWM2M_BIND_PORT_NO_SEC_BS:5691}" - bind_port_no_sec_rpk: "${LWM2M_BIND_PORT_NO_SEC_BS:5693}" - bind_port_no_sec_x509: "${LWM2M_BIND_PORT_NO_SEC_BS:5695}" + bind_port_no_sec: "${LWM2M_BIND_PORT_NO_SEC_BS:5687}" secure: - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" - start_psk: "${START_SERVER_PSK_BS:true}" - start_rpk: "${START_SERVER_RPK_BS:true}" - start_x509: "${START_SERVER_X509_BS:true}" - bind_port_psk: "${LWM2M_BIND_PORT_SEC_PSK_BS:5692}" - bind_port_rpk: "${LWM2M_BIND_PORT_SER_RPK_BS:5694}" - bind_port_x509: "${LWM2M_BIND_PORT_SEC_X509_BS:5696}" - # Only RPK: Public & Private Key + bind_address_security: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" + bind_port_security: "${LWM2M_BIND_PORT_SEC_BS:5688}" + # Only for RPK: Public & Private Key. If the keystore file is missing or not working public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}" public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}" private_s: "${LWM2M_SERVER_PRIVATE_S_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}" # Only Certificate_x509: alias: "${LWM2M_KEYSTORE_ALIAS_BOOTSTRAP:bootstrap}" - # Redis + # Redis redis_url: "${LWM2M_REDIS_URL:''}" + sessions: inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:30000}" diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts index ddbd58ab10..51d7735dd7 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/profile-config.models.ts @@ -27,7 +27,7 @@ export const DEFAULT_ID_SERVER = 123; export const DEFAULT_ID_BOOTSTRAP = 111; export const DEFAULT_HOST_NAME = 'localhost'; export const DEFAULT_PORT_SERVER_NO_SEC = 5685; -export const DEFAULT_PORT_BOOTSTRAP_NO_SEC = 5691; +export const DEFAULT_PORT_BOOTSTRAP_NO_SEC = 5686; export const DEFAULT_CLIENT_HOLD_OFF_TIME = 1; export const DEFAULT_LIFE_TIME = 300; export const DEFAULT_MIN_PERIOD = 1;