@ -13,12 +13,10 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License .
* limitations under the License .
* /
* /
package org.thingsboard.server.transport.lwm2m.bootstrap.secu re ;
package org.thingsboard.server.transport.lwm2m.bootstrap.sto re ;
import lombok.extern.slf4j.Slf4j ;
import lombok.extern.slf4j.Slf4j ;
import org.eclipse.leshan.core.SecurityMode ;
import org.eclipse.leshan.core.SecurityMode ;
import org.eclipse.leshan.core.util.Hex ;
import org.eclipse.leshan.core.util.SecurityUtil ;
import org.eclipse.leshan.server.bootstrap.BootstrapConfig ;
import org.eclipse.leshan.server.bootstrap.BootstrapConfig ;
import org.eclipse.leshan.server.bootstrap.EditableBootstrapConfigStore ;
import org.eclipse.leshan.server.bootstrap.EditableBootstrapConfigStore ;
import org.eclipse.leshan.server.bootstrap.InvalidConfigurationException ;
import org.eclipse.leshan.server.bootstrap.InvalidConfigurationException ;
@ -26,9 +24,10 @@ import org.eclipse.leshan.server.security.BootstrapSecurityStore;
import org.eclipse.leshan.server.security.SecurityInfo ;
import org.eclipse.leshan.server.security.SecurityInfo ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression ;
import org.springframework.stereotype.Service ;
import org.springframework.stereotype.Service ;
import org.thingsboard.common.util.JacksonUtil ;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode ;
import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServersConfiguration ;
import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.AbstractLwM2MBootstrapServerCredential ;
import org.thingsboard.server.gen.transport.TransportProtos ;
import org.thingsboard.server.gen.transport.TransportProtos ;
import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig ;
import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator ;
import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator ;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo ;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo ;
import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener ;
import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener ;
@ -42,12 +41,12 @@ import java.util.Iterator;
import java.util.Map ;
import java.util.Map ;
import java.util.UUID ;
import java.util.UUID ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.atomic.AtomicBoolean ;
import static org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer.BOOTSTRAP ;
import static org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer.BOOTSTRAP ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_ERROR ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_ERROR ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_INFO ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_INFO ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_TELEMETRY ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.LOG_LWM2M_TELEMETRY ;
import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.getBootstrapParametersFromThingsboard ;
@Slf4j
@Slf4j
@Service ( "LwM2MBootstrapSecurityStore" )
@Service ( "LwM2MBootstrapSecurityStore" )
@ -73,7 +72,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
public Iterator < SecurityInfo > getAllByEndpoint ( String endPoint ) {
public Iterator < SecurityInfo > getAllByEndpoint ( String endPoint ) {
// TODO
// TODO
TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator . getEndpointSecurityInfoByCredentialsId ( endPoint , BOOTSTRAP ) ;
TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator . getEndpointSecurityInfoByCredentialsId ( endPoint , BOOTSTRAP ) ;
if ( store . getBootstrapCredentialConfig ( ) ! = null & & store . getSecurityMode ( ) ! = null ) {
if ( store . getBootstrapCredentialConfig ( ) ! = null ) {
/* add value to store from BootstrapJson */
/* add value to store from BootstrapJson */
this . setBootstrapConfigScurityInfo ( store ) ;
this . setBootstrapConfigScurityInfo ( store ) ;
BootstrapConfig bsConfigNew = store . getBootstrapConfig ( ) ;
BootstrapConfig bsConfigNew = store . getBootstrapConfig ( ) ;
@ -123,15 +122,15 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
LwM2MBootstrapConfig lwM2MBootstrapConfig = this . getParametersBootstrap ( store ) ;
LwM2MBootstrapConfig lwM2MBootstrapConfig = this . getParametersBootstrap ( store ) ;
if ( lwM2MBootstrapConfig ! = null ) {
if ( lwM2MBootstrapConfig ! = null ) {
/* Security info */
/* Security info */
switch ( lwM2MBootstrapConfig . getBootstrapServer ( ) . getSecurityMode ( ) ) {
// switch (lwM2MBootstrapConfig.getBootstrapServer().getSecurityMode()) {
/* Use RPK only */
// /* Use RPK only */
c ase PSK :
// c ase PSK:
// store.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(store.getEndpoint(),
// store.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(store.getEndpoint(),
// lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId(),
// lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId(),
// Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientSecretKey().toCharArray())));
// Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientSecretKey().toCharArray())));
store . setSecurityMode ( SecurityMode . PSK ) ;
// store.setSecurityMode(SecurityMode.PSK);
break ;
// break;
c ase RPK :
// c ase RPK:
// try {
// try {
//// store.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(store.getEndpoint(),
//// store.setSecurityInfo(SecurityInfo.newRawPublicKeyInfo(store.getEndpoint(),
//// SecurityUtil.publicKey.decode(Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId().toCharArray()))));
//// SecurityUtil.publicKey.decode(Hex.decodeHex(lwM2MBootstrapConfig.getBootstrapServer().getClientPublicKeyOrId().toCharArray()))));
@ -140,16 +139,16 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
// } catch (IOException | GeneralSecurityException e) {
// } catch (IOException | GeneralSecurityException e) {
// log.error("Unable to decode Client public key for [{}] [{}]", store.getEndpoint(), e.getMessage());
// log.error("Unable to decode Client public key for [{}] [{}]", store.getEndpoint(), e.getMessage());
// }
// }
c ase X509 :
// c ase X509:
store . setSecurityInfo ( SecurityInfo . newX509CertInfo ( store . getEndpoint ( ) ) ) ;
// store.setSecurityInfo(SecurityInfo.newX509CertInfo(store.getEndpoint()));
store . setSecurityMode ( SecurityMode . X509 ) ;
// store.setSecurityMode(SecurityMode.X509);
break ;
// break;
c ase NO_SEC :
// c ase NO_SEC:
store . setSecurityMode ( SecurityMode . NO_SEC ) ;
// store.setSecurityMode(SecurityMode.NO_SEC);
store . setSecurityInfo ( null ) ;
// store.setSecurityInfo(null);
break ;
// break;
default :
// default:
}
// }
BootstrapConfig bootstrapConfig = lwM2MBootstrapConfig . getLwM2MBootstrapConfig ( ) ;
BootstrapConfig bootstrapConfig = lwM2MBootstrapConfig . getLwM2MBootstrapConfig ( ) ;
store . setBootstrapConfig ( bootstrapConfig ) ;
store . setBootstrapConfig ( bootstrapConfig ) ;
}
}
@ -158,7 +157,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
private LwM2MBootstrapConfig getParametersBootstrap ( TbLwM2MSecurityInfo store ) {
private LwM2MBootstrapConfig getParametersBootstrap ( TbLwM2MSecurityInfo store ) {
LwM2MBootstrapConfig lwM2MBootstrapConfig = store . getBootstrapCredentialConfig ( ) ;
LwM2MBootstrapConfig lwM2MBootstrapConfig = store . getBootstrapCredentialConfig ( ) ;
if ( lwM2MBootstrapConfig ! = null ) {
if ( lwM2MBootstrapConfig ! = null ) {
LwM2MBootstrapServersConfiguration bootstrapObject = getBootstrapParametersFromThingsboard ( store . getDeviceProfile ( ) ) ;
// LwM2MBootstrapServersConfiguration bootstrapObject = getBootstrapParametersFromThingsboard(store.getDeviceProfile());
// lwM2MBootstrapConfig.setServers(JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getServers()), LwM2MBootstrapServers.class));
// lwM2MBootstrapConfig.setServers(JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getServers()), LwM2MBootstrapServers.class));
// LwM2MServerBootstrap bootstrapServerProfile = JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getBootstrapServer()), LwM2MServerBootstrap.class);
// LwM2MServerBootstrap bootstrapServerProfile = JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getBootstrapServer()), LwM2MServerBootstrap.class);
// if (SecurityMode.NO_SEC != bootstrapServerProfile.getSecurityMode() && bootstrapServerProfile != null) {
// if (SecurityMode.NO_SEC != bootstrapServerProfile.getSecurityMode() && bootstrapServerProfile != null) {
@ -170,23 +169,25 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
// profileLwm2mServer.setSecurityHost(profileLwm2mServer.getHost());
// profileLwm2mServer.setSecurityHost(profileLwm2mServer.getHost());
// profileLwm2mServer.setSecurityPort(profileLwm2mServer.getPort());
// profileLwm2mServer.setSecurityPort(profileLwm2mServer.getPort());
// }
// }
// UUID sessionUUiD = UUID.randomUUID();
// TransportProtos.SessionInfoProto sessionInfo = helper.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits());
// bsSessions.put(store.getEndpoint(), sessionInfo);
UUID sessionUUiD = UUID . randomUUID ( ) ;
// context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, null, null, sessionInfo, context.getTransportService()));
TransportProtos . SessionInfoProto sessionInfo = helper . getValidateSessionInfo ( store . getMsg ( ) , sessionUUiD . getMostSignificantBits ( ) , sessionUUiD . getLeastSignificantBits ( ) ) ;
// if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.getBootstrapServer(), bootstrapServerProfile, lwM2MBootstrapConfig.getLwm2mServer(), profileLwm2mServer)) {
bsSessions . put ( store . getEndpoint ( ) , sessionInfo ) ;
context . getTransportService ( ) . registerAsyncSession ( sessionInfo , new LwM2mSessionMsgListener ( null , null , null , sessionInfo , context . getTransportService ( ) ) ) ;
if ( this . getValidatedSecurityMode ( lwM2MBootstrapConfig ) ) {
// lwM2MBootstrapConfig.setBootstrapServer(new LwM2MServerBootstrap(lwM2MBootstrapConfig.getBootstrapServer(), bootstrapServerProfile));
// lwM2MBootstrapConfig.setBootstrapServer(new LwM2MServerBootstrap(lwM2MBootstrapConfig.getBootstrapServer(), bootstrapServerProfile));
// lwM2MBootstrapConfig.setLwm2mServer(new LwM2MServerBootstrap(lwM2MBootstrapConfig.getLwm2mServer(), profileLwm2mServer));
// lwM2MBootstrapConfig.setLwm2mServer(new LwM2MServerBootstrap(lwM2MBootstrapConfig.getLwm2mServer(), profileLwm2mServer));
// String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LWM2M_INFO, store.getEndpoint());
String logMsg = String . format ( "%s: getParametersBootstrap: %s Access connect client with bootstrap server." , LOG_LWM2M_INFO , store . getEndpoint ( ) ) ;
// helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LWM2M_TELEMETRY, logMsg), sessionInfo);
helper . sendParametersOnThingsboardTelemetry ( helper . getKvStringtoThingsboard ( LOG_LWM2M_TELEMETRY , logMsg ) , sessionInfo ) ;
// return lwM2MBootstrapConfig;
return lwM2MBootstrapConfig ;
// } else {
} else {
// log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndpoint());
log . error ( " [{}] Different values SecurityMode between of client and profile." , store . getEndpoint ( ) ) ;
// log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LWM2M_ERROR, store.getEndpoint());
log . error ( "{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile." , LOG_LWM2M_ERROR , store . getEndpoint ( ) ) ;
// String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LWM2M_ERROR, store.getEndpoint());
String logMsg = String . format ( "%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile." , LOG_LWM2M_ERROR , store . getEndpoint ( ) ) ;
// helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LWM2M_TELEMETRY, logMsg), sessionInfo);
helper . sendParametersOnThingsboardTelemetry ( helper . getKvStringtoThingsboard ( LOG_LWM2M_TELEMETRY , logMsg ) , sessionInfo ) ;
// return null;
return null ;
// }
}
}
}
log . error ( "Unable to decode Json or Certificate for [{}]" , store . getEndpoint ( ) ) ;
log . error ( "Unable to decode Json or Certificate for [{}]" , store . getEndpoint ( ) ) ;
return null ;
return null ;
@ -196,15 +197,27 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
* Bootstrap security have to sync between ( bootstrapServer in credential and bootstrapServer in profile )
* Bootstrap security have to sync between ( bootstrapServer in credential and bootstrapServer in profile )
* and ( lwm2mServer in credential and lwm2mServer in profile
* and ( lwm2mServer in credential and lwm2mServer in profile
*
*
* @param bootstrapFromCredential - Bootstrap - > Security of bootstrapServer in credential
* @param bootstrapServerProfile - Bootstrap - > Security of bootstrapServer in profile
* @param lwm2mFromCredential - Bootstrap - > Security of lwm2mServer in credential
* @param profileLwm2mServer - Bootstrap - > Security of lwm2mServer in profile
* @return false if not sync between SecurityMode of Bootstrap credential and profile
* @return false if not sync between SecurityMode of Bootstrap credential and profile
* /
* /
private boolean getValidatedSecurityMode ( LwM2MServerBootstrap bootstrapFromCredential , LwM2MServerBootstrap bootstrapServerProfile , LwM2MServerBootstrap lwm2mFromCredential , LwM2MServerBootstrap profileLwm2mServer ) {
// private boolean getValidatedSecurityMode(LwM2MServerBootstrap bootstrapFromCredential, LwM2MServerBootstrap bootstrapServerProfile, LwM2MServerBootstrap lwm2mFromCredential, LwM2MServerBootstrap profileLwm2mServer) {
return ( bootstrapFromCredential . getSecurityMode ( ) . equals ( bootstrapServerProfile . getSecurityMode ( ) ) & &
private boolean getValidatedSecurityMode ( LwM2MBootstrapConfig lwM2MBootstrapConfig ) {
lwm2mFromCredential . getSecurityMode ( ) . equals ( profileLwm2mServer . getSecurityMode ( ) ) ) ;
LwM2MSecurityMode bootstrapServerSecurityMode = lwM2MBootstrapConfig . getBootstrapServer ( ) . getSecurityMode ( ) ;
LwM2MSecurityMode lwm2mServerSecurityMode = lwM2MBootstrapConfig . getLwm2mServer ( ) . getSecurityMode ( ) ;
AtomicBoolean validBs = new AtomicBoolean ( true ) ;
AtomicBoolean validLw = new AtomicBoolean ( true ) ;
lwM2MBootstrapConfig . getServerConfiguration ( ) . forEach ( serverCredential - > {
if ( ( ( AbstractLwM2MBootstrapServerCredential ) serverCredential ) . isBootstrapServerIs ( ) ) {
if ( ! bootstrapServerSecurityMode . equals ( serverCredential . getSecurityMode ( ) ) ) {
validBs . set ( false ) ;
}
}
else {
if ( ! lwm2mServerSecurityMode . equals ( serverCredential . getSecurityMode ( ) ) ) {
validLw . set ( false ) ;
}
}
} ) ;
return validBs . get ( ) & validLw . get ( ) ;
}
}
public TransportProtos . SessionInfoProto getSessionByEndpoint ( String endpoint ) {
public TransportProtos . SessionInfoProto getSessionByEndpoint ( String endpoint ) {