Fix initialization order

This commit is contained in:
Andrii Shvaika 2021-06-07 19:24:25 +03:00
parent 626b6620dd
commit 74dc1c9df1
16 changed files with 346 additions and 166 deletions

View File

@ -30,7 +30,7 @@ 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.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator; import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
@ -72,7 +72,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
@Override @Override
public Iterator<SecurityInfo> getAllByEndpoint(String endPoint) { public Iterator<SecurityInfo> getAllByEndpoint(String endPoint) {
EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP); TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfoByCredentialsId(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) {
/* add value to store from BootstrapJson */ /* add value to store from BootstrapJson */
this.setBootstrapConfigScurityInfo(store); this.setBootstrapConfigScurityInfo(store);
@ -96,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
@Override @Override
public SecurityInfo getByIdentity(String identity) { public SecurityInfo getByIdentity(String identity) {
EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP); TbLwM2MSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfoByCredentialsId(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) { if (store.getBootstrapCredentialConfig() != null && store.getSecurityMode() != null) {
/* add value to store from BootstrapJson */ /* add value to store from BootstrapJson */
this.setBootstrapConfigScurityInfo(store); this.setBootstrapConfigScurityInfo(store);
@ -113,7 +113,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
return null; return null;
} }
private void setBootstrapConfigScurityInfo(EndpointSecurityInfo store) { private void setBootstrapConfigScurityInfo(TbLwM2MSecurityInfo store) {
/* BootstrapConfig */ /* BootstrapConfig */
LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store); LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store);
if (lwM2MBootstrapConfig != null) { if (lwM2MBootstrapConfig != null) {
@ -150,7 +150,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
} }
} }
private LwM2MBootstrapConfig getParametersBootstrap(EndpointSecurityInfo store) { private LwM2MBootstrapConfig getParametersBootstrap(TbLwM2MSecurityInfo store) {
try { try {
LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig(); LwM2MBootstrapConfig lwM2MBootstrapConfig = store.getBootstrapCredentialConfig();
if (lwM2MBootstrapConfig != null) { if (lwM2MBootstrapConfig != null) {

View File

@ -55,15 +55,15 @@ public class LwM2mCredentialsSecurityInfoValidator {
private final LwM2mTransportContext context; private final LwM2mTransportContext context;
private final LwM2MTransportServerConfig config; private final LwM2MTransportServerConfig config;
public EndpointSecurityInfo getEndpointSecurityInfo(String endpoint, LwM2mTransportUtil.LwM2mTypeServer keyValue) { public TbLwM2MSecurityInfo getEndpointSecurityInfoByCredentialsId(String credentialsId, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
final EndpointSecurityInfo[] resultSecurityStore = new EndpointSecurityInfo[1]; final TbLwM2MSecurityInfo[] resultSecurityStore = new TbLwM2MSecurityInfo[1];
context.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(), context.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(credentialsId).build(),
new TransportServiceCallback<>() { new TransportServiceCallback<>() {
@Override @Override
public void onSuccess(ValidateDeviceCredentialsResponse msg) { public void onSuccess(ValidateDeviceCredentialsResponse msg) {
String credentialsBody = msg.getCredentials(); String credentialsBody = msg.getCredentials();
resultSecurityStore[0] = createSecurityInfo(endpoint, credentialsBody, keyValue); resultSecurityStore[0] = createSecurityInfo(credentialsId, credentialsBody, keyValue);
resultSecurityStore[0].setMsg(msg); resultSecurityStore[0].setMsg(msg);
resultSecurityStore[0].setDeviceProfile(msg.getDeviceProfile()); resultSecurityStore[0].setDeviceProfile(msg.getDeviceProfile());
latch.countDown(); latch.countDown();
@ -71,8 +71,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
log.trace("[{}] [{}] Failed to process credentials ", endpoint, e); log.trace("[{}] [{}] Failed to process credentials ", credentialsId, e);
resultSecurityStore[0] = createSecurityInfo(endpoint, null, null); resultSecurityStore[0] = createSecurityInfo(credentialsId, null, null);
latch.countDown(); latch.countDown();
} }
}); });
@ -91,8 +91,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
* @param keyValue - * @param keyValue -
* @return SecurityInfo * @return SecurityInfo
*/ */
private EndpointSecurityInfo createSecurityInfo(String endpoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) { private TbLwM2MSecurityInfo createSecurityInfo(String endpoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
EndpointSecurityInfo result = new EndpointSecurityInfo(); TbLwM2MSecurityInfo result = new TbLwM2MSecurityInfo();
LwM2MCredentials credentials = JacksonUtil.fromString(jsonStr, LwM2MCredentials.class); LwM2MCredentials credentials = JacksonUtil.fromString(jsonStr, LwM2MCredentials.class);
if (credentials != null) { if (credentials != null) {
if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) { if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) {
@ -106,7 +106,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
} else { } else {
switch (credentials.getClient().getSecurityConfigClientMode()) { switch (credentials.getClient().getSecurityConfigClientMode()) {
case NO_SEC: case NO_SEC:
createClientSecurityInfoNoSec(result); createClientSecurityInfoNoSec(result, endpoint);
break; break;
case PSK: case PSK:
createClientSecurityInfoPSK(result, endpoint, credentials.getClient()); createClientSecurityInfoPSK(result, endpoint, credentials.getClient());
@ -125,12 +125,13 @@ public class LwM2mCredentialsSecurityInfoValidator {
return result; return result;
} }
private void createClientSecurityInfoNoSec(EndpointSecurityInfo result) { private void createClientSecurityInfoNoSec(TbLwM2MSecurityInfo result, String endpoint) {
result.setEndpoint(endpoint);
result.setSecurityInfo(null); result.setSecurityInfo(null);
result.setSecurityMode(NO_SEC); result.setSecurityMode(NO_SEC);
} }
private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { private void createClientSecurityInfoPSK(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
PSKClientCredentials pskConfig = (PSKClientCredentials) clientCredentialsConfig; PSKClientCredentials pskConfig = (PSKClientCredentials) clientCredentialsConfig;
if (StringUtils.isNotEmpty(pskConfig.getIdentity())) { if (StringUtils.isNotEmpty(pskConfig.getIdentity())) {
try { try {
@ -149,7 +150,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
} }
} }
private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { private void createClientSecurityInfoRPK(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
RPKClientCredentials rpkConfig = (RPKClientCredentials) clientCredentialsConfig; RPKClientCredentials rpkConfig = (RPKClientCredentials) clientCredentialsConfig;
try { try {
if (rpkConfig.getKey() != null) { if (rpkConfig.getKey() != null) {
@ -164,7 +165,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
} }
} }
private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) { private void createClientSecurityInfoX509(TbLwM2MSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint)); result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint));
result.setSecurityMode(X509); result.setSecurityMode(X509);
} }

View File

@ -27,6 +27,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore;
import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
@ -34,7 +35,7 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore;
public class TbLwM2MAuthorizer implements Authorizer { public class TbLwM2MAuthorizer implements Authorizer {
private final TbLwM2MDtlsSessionStore sessionStorage; private final TbLwM2MDtlsSessionStore sessionStorage;
private final TbLwM2mSecurityStore securityStore; private final TbSecurityStore securityStore;
private final SecurityChecker securityChecker = new SecurityChecker(); private final SecurityChecker securityChecker = new SecurityChecker();
private final LwM2mClientContext clientContext; private final LwM2mClientContext clientContext;

View File

@ -24,7 +24,7 @@ import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsRes
import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig; import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig;
@Data @Data
public class EndpointSecurityInfo { public class TbLwM2MSecurityInfo {
private ValidateDeviceCredentialsResponse msg; private ValidateDeviceCredentialsResponse msg;
private SecurityInfo securityInfo; private SecurityInfo securityInfo;
private SecurityMode securityMode; private SecurityMode securityMode;

View File

@ -357,7 +357,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
*/ */
@Override @Override
public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo); LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) { if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) {
log.warn("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList()); log.warn("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList());
msg.getSharedUpdatedList().forEach(tsKvProto -> { msg.getSharedUpdatedList().forEach(tsKvProto -> {
@ -459,7 +459,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime()); this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime());
Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; Lwm2mClientRpcRequest lwm2mClientRpcRequest = null;
try { try {
Registration registration = clientContext.getClient(sessionInfo).getRegistration(); Registration registration = clientContext.getClientBySessionInfo(sessionInfo).getRegistration();
lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this); lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this);
if (lwm2mClientRpcRequest.getErrorMsg() != null) { if (lwm2mClientRpcRequest.getErrorMsg() != null) {
lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
@ -789,7 +789,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
lwM2MClient.getPendingReadRequests().addAll(pathSend); lwM2MClient.getPendingReadRequests().addAll(pathSend);
ConcurrentHashMap<String, Object> finalParams = params; ConcurrentHashMap<String, Object> finalParams = params;
pathSend.forEach(target -> { pathSend.forEach(target -> {
lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(), lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TEXT.getName(),
finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null); finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null);
}); });
if (OBSERVE.equals(typeOper)) { if (OBSERVE.equals(typeOper)) {
@ -1159,7 +1159,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
.collect(Collectors.toUnmodifiableSet()); .collect(Collectors.toUnmodifiableSet());
if (!pathSend.isEmpty()) { if (!pathSend.isEmpty()) {
ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew; ConcurrentHashMap<String, Object> finalParams = lwm2mAttributesNew;
pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TEXT.getName(),
finalParams.get(target), this.config.getTimeout(), null)); finalParams.get(target), this.config.getTimeout(), null));
} }
}); });
@ -1176,7 +1176,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
Map<String, Object> params = (Map<String, Object>) lwm2mAttributesOld.get(target); Map<String, Object> params = (Map<String, Object>) lwm2mAttributesOld.get(target);
params.clear(); params.clear();
params.put(OBJECT_VERSION, ""); params.put(OBJECT_VERSION, "");
lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TLV.getName(), lwM2mTransportRequest.sendAllRequest(registration, target, WRITE_ATTRIBUTES, ContentFormat.TEXT.getName(),
params, this.config.getTimeout(), null); params, this.config.getTimeout(), null);
}); });
} }
@ -1227,7 +1227,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
*/ */
public String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { public String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
LwM2mClient lwM2mClient = clientContext.getClient(sessionInfo); LwM2mClient lwM2mClient = clientContext.getClientBySessionInfo(sessionInfo);
return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
.filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey) .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
.orElse(null); .orElse(null);
@ -1262,7 +1262,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
* @param sessionInfo * @param sessionInfo
*/ */
public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) { public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo); LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
if (lwM2MClient != null) { if (lwM2MClient != null) {
log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos); log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos);
tsKvProtos.forEach(tsKvProto -> { tsKvProtos.forEach(tsKvProto -> {

View File

@ -36,6 +36,8 @@ import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore;
import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -83,7 +85,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
private final LwM2mTransportServerHelper helper; private final LwM2mTransportServerHelper helper;
private final LwM2mTransportMsgHandler handler; private final LwM2mTransportMsgHandler handler;
private final CaliforniumRegistrationStore registrationStore; private final CaliforniumRegistrationStore registrationStore;
private final EditableSecurityStore securityStore; private final TbSecurityStore securityStore;
private final LwM2mClientContext lwM2mClientContext; private final LwM2mClientContext lwM2mClientContext;
private final TbLwM2MDtlsCertificateVerifier certificateVerifier; private final TbLwM2MDtlsCertificateVerifier certificateVerifier;
private final TbLwM2MAuthorizer authorizer; private final TbLwM2MAuthorizer authorizer;

View File

@ -76,7 +76,6 @@ public class LwM2mClient implements Cloneable {
@Getter @Getter
private final Map<String, TsKvProto> delayedRequests; private final Map<String, TsKvProto> delayedRequests;
@Getter @Getter
@Setter
private final List<String> pendingReadRequests; private final List<String> pendingReadRequests;
@Getter @Getter
private final Queue<LwM2mQueuedRequest> queuedRequests; private final Queue<LwM2mQueuedRequest> queuedRequests;

View File

@ -32,15 +32,14 @@ public interface LwM2mClientContext {
LwM2mClient getClientByEndpoint(String endpoint); LwM2mClient getClientByEndpoint(String endpoint);
LwM2mClient getClientBySessionInfo(TransportProtos.SessionInfoProto sessionInfo);
void register(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException; void register(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException;
void updateRegistration(LwM2mClient client, Registration registration) throws LwM2MClientStateException; void updateRegistration(LwM2mClient client, Registration registration) throws LwM2MClientStateException;
void unregister(LwM2mClient client, Registration registration) throws LwM2MClientStateException; void unregister(LwM2mClient client, Registration registration) throws LwM2MClientStateException;
SecurityInfo fetchSecurityInfoByCredentials(String credentialsId);
LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo);
// LwM2mClient getOrRegister(Registration registration); // LwM2mClient getOrRegister(Registration registration);

View File

@ -25,11 +25,11 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
import org.thingsboard.server.transport.lwm2m.server.store.TbEditableSecurityStore;
import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -40,8 +40,6 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static org.eclipse.leshan.core.SecurityMode.NO_SEC; import static org.eclipse.leshan.core.SecurityMode.NO_SEC;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
@Slf4j @Slf4j
@ -51,14 +49,11 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c
public class LwM2mClientContextImpl implements LwM2mClientContext { public class LwM2mClientContextImpl implements LwM2mClientContext {
private final LwM2mTransportContext context; private final LwM2mTransportContext context;
private final TbEditableSecurityStore securityStore;
private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>(); private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>();
private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>(); private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>();
private Map<UUID, LwM2mClientProfile> profiles = new ConcurrentHashMap<>(); private Map<UUID, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;
private final EditableSecurityStore securityStore;
@Override @Override
public LwM2mClient getClientByEndpoint(String endpoint) { public LwM2mClient getClientByEndpoint(String endpoint) {
return lwM2mClientsByEndpoint.computeIfAbsent(endpoint, ep -> new LwM2mClient(context.getNodeId(), ep)); return lwM2mClientsByEndpoint.computeIfAbsent(endpoint, ep -> new LwM2mClient(context.getNodeId(), ep));
@ -71,8 +66,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
if (LwM2MClientState.UNREGISTERED.equals(lwM2MClient.getState())) { if (LwM2MClientState.UNREGISTERED.equals(lwM2MClient.getState())) {
throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state."); throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
} }
//TODO: Move this security info lookup to the TbLwM2mSecurityStore. TbLwM2MSecurityInfo securityInfo = securityStore.getTbLwM2MSecurityInfoByEndpoint(lwM2MClient.getEndpoint());
EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(lwM2MClient.getEndpoint(), LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
if (securityInfo.getSecurityMode() != null) { if (securityInfo.getSecurityMode() != null) {
if (securityInfo.getDeviceProfile() != null) { if (securityInfo.getDeviceProfile() != null) {
UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile()) != null ? securityInfo.getDeviceProfile().getUuidId() : null; UUID profileUuid = profileUpdate(securityInfo.getDeviceProfile()) != null ? securityInfo.getDeviceProfile().getUuidId() : null;
@ -127,7 +121,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
if (currentRegistration.getId().equals(registration.getId())) { if (currentRegistration.getId().equals(registration.getId())) {
lwM2MClient.setState(LwM2MClientState.UNREGISTERED); lwM2MClient.setState(LwM2MClientState.UNREGISTERED);
lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint()); lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());
this.securityStore.remove(lwM2MClient.getEndpoint(), false); this.securityStore.remove(lwM2MClient.getEndpoint());
this.lwM2mClientsByRegistrationId.remove(registration.getId()); this.lwM2mClientsByRegistrationId.remove(registration.getId());
UUID profileId = lwM2MClient.getProfileId(); UUID profileId = lwM2MClient.getProfileId();
if (profileId != null) { if (profileId != null) {
@ -144,18 +138,13 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
} }
} }
@Override
public LwM2mClient fetchSecurityInfoByCredentials(String credentialsId) {
return null;
}
@Override @Override
public LwM2mClient getClientByRegistrationId(String registrationId) { public LwM2mClient getClientByRegistrationId(String registrationId) {
return lwM2mClientsByRegistrationId.get(registrationId); return lwM2mClientsByRegistrationId.get(registrationId);
} }
@Override @Override
public LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo) { public LwM2mClient getClientBySessionInfo(TransportProtos.SessionInfoProto sessionInfo) {
LwM2mClient lwM2mClient = lwM2mClientsByEndpoint.values().stream().filter(c -> LwM2mClient lwM2mClient = lwM2mClientsByEndpoint.values().stream().filter(c ->
(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())) (new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()))
.equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB()))) .equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())))

View File

@ -273,7 +273,7 @@ public class Lwm2mClientRpcRequest {
} }
private String getRezIdByResourceNameAndObjectInstanceId(String resourceName, DefaultLwM2MTransportMsgHandler handler) { private String getRezIdByResourceNameAndObjectInstanceId(String resourceName, DefaultLwM2MTransportMsgHandler handler) {
LwM2mClient lwM2mClient = handler.clientContext.getClient(this.sessionInfo); LwM2mClient lwM2mClient = handler.clientContext.getClientBySessionInfo(this.sessionInfo);
return lwM2mClient != null ? return lwM2mClient != null ?
lwM2mClient.getRezIdByResourceNameAndObjectInstanceId(resourceName, this.targetIdVer, handler.config.getModelProvider()) : lwM2mClient.getRezIdByResourceNameAndObjectInstanceId(resourceName, this.targetIdVer, handler.config.getModelProvider()) :
null; null;

View File

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2021 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.store;
import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
public interface TbEditableSecurityStore extends TbSecurityStore {
void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException;
void remove(String endpoint);
}

View File

@ -0,0 +1,130 @@
/**
* Copyright © 2016-2021 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.store;
import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
import org.eclipse.leshan.server.security.SecurityInfo;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TbInMemorySecurityStore implements TbEditableSecurityStore {
// lock for the two maps
protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
protected final Lock readLock = readWriteLock.readLock();
protected final Lock writeLock = readWriteLock.writeLock();
// by client end-point
protected Map<String, TbLwM2MSecurityInfo> securityByEp = new HashMap<>();
// by PSK identity
protected Map<String, TbLwM2MSecurityInfo> securityByIdentity = new HashMap<>();
public TbInMemorySecurityStore() {
}
/**
* {@inheritDoc}
*/
@Override
public SecurityInfo getByEndpoint(String endpoint) {
readLock.lock();
try {
TbLwM2MSecurityInfo securityInfo = securityByEp.get(endpoint);
if (securityInfo != null) {
return securityInfo.getSecurityInfo();
} else {
return null;
}
} finally {
readLock.unlock();
}
}
/**
* {@inheritDoc}
*/
@Override
public SecurityInfo getByIdentity(String identity) {
readLock.lock();
try {
TbLwM2MSecurityInfo securityInfo = securityByIdentity.get(identity);
if (securityInfo != null) {
return securityInfo.getSecurityInfo();
} else {
return null;
}
} finally {
readLock.unlock();
}
}
@Override
public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException {
writeLock.lock();
try {
String identity = null;
if (tbSecurityInfo.getSecurityInfo() != null) {
identity = tbSecurityInfo.getSecurityInfo().getIdentity();
if (identity != null) {
TbLwM2MSecurityInfo infoByIdentity = securityByIdentity.get(identity);
if (infoByIdentity != null && !tbSecurityInfo.getSecurityInfo().getEndpoint().equals(infoByIdentity.getEndpoint())) {
throw new NonUniqueSecurityInfoException("PSK Identity " + identity + " is already used");
}
securityByIdentity.put(tbSecurityInfo.getSecurityInfo().getIdentity(), tbSecurityInfo);
}
}
TbLwM2MSecurityInfo previous = securityByEp.put(tbSecurityInfo.getEndpoint(), tbSecurityInfo);
if (previous != null && previous.getSecurityInfo() != null) {
String previousIdentity = previous.getSecurityInfo().getIdentity();
if (previousIdentity != null && !previousIdentity.equals(identity)) {
securityByIdentity.remove(previousIdentity);
}
}
} finally {
writeLock.unlock();
}
}
@Override
public void remove(String endpoint) {
writeLock.lock();
try {
TbLwM2MSecurityInfo securityInfo = securityByEp.remove(endpoint);
if (securityInfo != null && securityInfo.getSecurityInfo() != null && securityInfo.getSecurityInfo().getIdentity() != null) {
securityByIdentity.remove(securityInfo.getSecurityInfo().getIdentity());
}
} finally {
writeLock.unlock();
}
}
@Override
public TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint) {
readLock.lock();
try {
return securityByEp.get(endpoint);
} finally {
readLock.unlock();
}
}
}

View File

@ -24,13 +24,14 @@ import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.ScanOptions;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
public class TbLwM2mRedisSecurityStore implements EditableSecurityStore { public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore {
private static final String SEC_EP = "SEC#EP#"; private static final String SEC_EP = "SEC#EP#";
private static final String PSKID_SEC = "PSKID#SEC"; private static final String PSKID_SEC = "PSKID#SEC";
@ -72,73 +73,89 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore {
} }
@Override @Override
public Collection<SecurityInfo> getAll() { public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException {
try (var connection = connectionFactory.getConnection()) { //TODO: implement
Collection<SecurityInfo> list = new LinkedList<>();
ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(SEC_EP + "*").build();
List<Cursor<byte[]>> scans = new ArrayList<>();
if (connection instanceof RedisClusterConnection) {
((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> {
scans.add(((RedisClusterConnection) connection).scan(node, scanOptions));
});
} else {
scans.add(connection.scan(scanOptions));
}
scans.forEach(scan -> {
scan.forEachRemaining(key -> {
byte[] element = connection.get(key);
list.add(deserialize(element));
});
});
return list;
}
} }
@Override @Override
public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { public TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint) {
byte[] data = serialize(info); //TODO: implement
try (var connection = connectionFactory.getConnection()) {
if (info.getIdentity() != null) {
// populate the secondary index (security info by PSK id)
String oldEndpoint = new String(connection.hGet(PSKID_SEC.getBytes(), info.getIdentity().getBytes()));
if (!oldEndpoint.equals(info.getEndpoint())) {
throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used");
}
connection.hSet(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes());
}
byte[] previousData = connection.getSet((SEC_EP + info.getEndpoint()).getBytes(), data);
SecurityInfo previous = previousData == null ? null : deserialize(previousData);
String previousIdentity = previous == null ? null : previous.getIdentity();
if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) {
connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes());
}
return previous;
}
}
@Override
public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
try (var connection = connectionFactory.getConnection()) {
byte[] data = connection.get((SEC_EP + endpoint).getBytes());
if (data != null) {
SecurityInfo info = deserialize(data);
if (info.getIdentity() != null) {
connection.hDel(PSKID_SEC.getBytes(), info.getIdentity().getBytes());
}
connection.del((SEC_EP + endpoint).getBytes());
if (listener != null) {
listener.securityInfoRemoved(infosAreCompromised, info);
}
return info;
}
}
return null; return null;
} }
@Override
public void remove(String endpoint) {
//TODO: implement
}
// @Override
// public Collection<SecurityInfo> getAll() {
// try (var connection = connectionFactory.getConnection()) {
// Collection<SecurityInfo> list = new LinkedList<>();
// ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(SEC_EP + "*").build();
// List<Cursor<byte[]>> scans = new ArrayList<>();
// if (connection instanceof RedisClusterConnection) {
// ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> {
// scans.add(((RedisClusterConnection) connection).scan(node, scanOptions));
// });
// } else {
// scans.add(connection.scan(scanOptions));
// }
//
// scans.forEach(scan -> {
// scan.forEachRemaining(key -> {
// byte[] element = connection.get(key);
// list.add(deserialize(element));
// });
// });
// return list;
// }
// }
//
// @Override
// public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
// byte[] data = serialize(info);
// try (var connection = connectionFactory.getConnection()) {
// if (info.getIdentity() != null) {
// // populate the secondary index (security info by PSK id)
// String oldEndpoint = new String(connection.hGet(PSKID_SEC.getBytes(), info.getIdentity().getBytes()));
// if (!oldEndpoint.equals(info.getEndpoint())) {
// throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used");
// }
// connection.hSet(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes());
// }
//
// byte[] previousData = connection.getSet((SEC_EP + info.getEndpoint()).getBytes(), data);
// SecurityInfo previous = previousData == null ? null : deserialize(previousData);
// String previousIdentity = previous == null ? null : previous.getIdentity();
// if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) {
// connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes());
// }
//
// return previous;
// }
// }
//
// @Override
// public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
// try (var connection = connectionFactory.getConnection()) {
// byte[] data = connection.get((SEC_EP + endpoint).getBytes());
//
// if (data != null) {
// SecurityInfo info = deserialize(data);
// if (info.getIdentity() != null) {
// connection.hDel(PSKID_SEC.getBytes(), info.getIdentity().getBytes());
// }
// connection.del((SEC_EP + endpoint).getBytes());
// if (listener != null) {
// listener.securityInfoRemoved(infosAreCompromised, info);
// }
// return info;
// }
// }
// return null;
// }
private byte[] serialize(SecurityInfo secInfo) { private byte[] serialize(SecurityInfo secInfo) {
return SecurityInfoSerDes.serialize(secInfo); return SecurityInfoSerDes.serialize(secInfo);
} }
@ -147,8 +164,4 @@ public class TbLwM2mRedisSecurityStore implements EditableSecurityStore {
return SecurityInfoSerDes.deserialize(data); return SecurityInfoSerDes.deserialize(data);
} }
@Override
public void setListener(SecurityStoreListener listener) {
this.listener = listener;
}
} }

View File

@ -19,63 +19,40 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.server.security.EditableSecurityStore; import org.eclipse.leshan.server.security.EditableSecurityStore;
import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
import org.eclipse.leshan.server.security.SecurityInfo; import org.eclipse.leshan.server.security.SecurityInfo;
import org.eclipse.leshan.server.security.SecurityStore;
import org.eclipse.leshan.server.security.SecurityStoreListener; import org.eclipse.leshan.server.security.SecurityStoreListener;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import java.util.Collection; import java.util.Collection;
@Slf4j @Slf4j
@Component
@TbLwM2mTransportComponent @TbLwM2mTransportComponent
public class TbLwM2mSecurityStore implements EditableSecurityStore { public class TbLwM2mSecurityStore implements TbEditableSecurityStore {
private final LwM2mClientContext clientContext; private final TbEditableSecurityStore securityStore;
private final EditableSecurityStore securityStore; private final LwM2mCredentialsSecurityInfoValidator validator;
public TbLwM2mSecurityStore(LwM2mClientContext clientContext, EditableSecurityStore securityStore) { public TbLwM2mSecurityStore(TbEditableSecurityStore securityStore, LwM2mCredentialsSecurityInfoValidator validator) {
this.clientContext = clientContext;
this.securityStore = securityStore; this.securityStore = securityStore;
this.validator = validator;
} }
@Override @Override
public Collection<SecurityInfo> getAll() { public TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint) {
return securityStore.getAll(); return securityStore.getTbLwM2MSecurityInfoByEndpoint(endpoint);
}
@Override
public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
return securityStore.add(info);
}
@Override
public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
return securityStore.remove(endpoint, infosAreCompromised);
}
@Override
public void setListener(SecurityStoreListener listener) {
securityStore.setListener(listener);
} }
@Override @Override
public SecurityInfo getByEndpoint(String endpoint) { public SecurityInfo getByEndpoint(String endpoint) {
SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint); SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint);
if (securityInfo == null) { if (securityInfo == null) {
LwM2mClient lwM2mClient = clientContext.getClientByEndpoint(endpoint); securityInfo = fetchAndPutSecurityInfo(endpoint);
if (lwM2mClient != null && lwM2mClient.getRegistration() != null && !lwM2mClient.getRegistration().getIdentity().isSecure()) {
return null;
}
securityInfo = clientContext.fetchSecurityInfoByCredentials(endpoint);
try {
if (securityInfo != null) {
add(securityInfo);
}
} catch (NonUniqueSecurityInfoException e) {
log.trace("Failed to add security info: {}", securityInfo, e);
}
} }
return securityInfo; return securityInfo;
} }
@ -84,15 +61,31 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore {
public SecurityInfo getByIdentity(String pskIdentity) { public SecurityInfo getByIdentity(String pskIdentity) {
SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity); SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity);
if (securityInfo == null) { if (securityInfo == null) {
securityInfo = clientContext.fetchSecurityInfoByCredentials(pskIdentity); securityInfo = fetchAndPutSecurityInfo(pskIdentity);
try {
if (securityInfo != null) {
add(securityInfo);
}
} catch (NonUniqueSecurityInfoException e) {
log.trace("Failed to add security info: {}", securityInfo, e);
}
} }
return securityInfo; return securityInfo;
} }
@Nullable
public SecurityInfo fetchAndPutSecurityInfo(String credentialsId) {
TbLwM2MSecurityInfo securityInfo = validator.getEndpointSecurityInfoByCredentialsId(credentialsId, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
try {
if (securityInfo != null) {
securityStore.put(securityInfo);
}
} catch (NonUniqueSecurityInfoException e) {
log.trace("Failed to add security info: {}", securityInfo, e);
}
return securityInfo != null ? securityInfo.getSecurityInfo() : null;
}
@Override
public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException {
securityStore.put(tbSecurityInfo);
}
@Override
public void remove(String endpoint) {
securityStore.remove(endpoint);
}
} }

View File

@ -19,6 +19,7 @@ import org.eclipse.leshan.server.californium.registration.CaliforniumRegistratio
import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore; import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore;
import org.eclipse.leshan.server.security.EditableSecurityStore; import org.eclipse.leshan.server.security.EditableSecurityStore;
import org.eclipse.leshan.server.security.InMemorySecurityStore; import org.eclipse.leshan.server.security.InMemorySecurityStore;
import org.eclipse.leshan.server.security.SecurityStore;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -27,6 +28,7 @@ import org.springframework.stereotype.Component;
import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
import java.util.Optional; import java.util.Optional;
@ -42,8 +44,7 @@ public class TbLwM2mStoreFactory {
private LwM2MTransportServerConfig config; private LwM2MTransportServerConfig config;
@Autowired @Autowired
@Lazy private LwM2mCredentialsSecurityInfoValidator validator;
private LwM2mClientContext clientContext;
@Value("${transport.lwm2m.redis.enabled:false}") @Value("${transport.lwm2m.redis.enabled:false}")
private boolean useRedis; private boolean useRedis;
@ -55,9 +56,9 @@ public class TbLwM2mStoreFactory {
} }
@Bean @Bean
private EditableSecurityStore securityStore() { private TbSecurityStore securityStore() {
return new TbLwM2mSecurityStore(clientContext, redisConfiguration.isPresent() && useRedis ? return new TbLwM2mSecurityStore(redisConfiguration.isPresent() && useRedis ?
new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new InMemorySecurityStore()); new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new TbInMemorySecurityStore(), validator);
} }
@Bean @Bean

View File

@ -0,0 +1,25 @@
/**
* Copyright © 2016-2021 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.store;
import org.eclipse.leshan.server.security.SecurityStore;
import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
public interface TbSecurityStore extends SecurityStore {
TbLwM2MSecurityInfo getTbLwM2MSecurityInfoByEndpoint(String endpoint);
}