Add ability to upgrade device credentials if chain match with uploaded device profile certificate.
This commit is contained in:
parent
dccc19a9b6
commit
5d35fa1f26
@ -65,8 +65,8 @@ import org.thingsboard.server.common.msg.EncryptionUtil;
|
|||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
import org.thingsboard.server.common.msg.TbMsgDataType;
|
import org.thingsboard.server.common.msg.TbMsgDataType;
|
||||||
import org.thingsboard.server.common.msg.TbMsgMetaData;
|
import org.thingsboard.server.common.msg.TbMsgMetaData;
|
||||||
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
|
|
||||||
import org.thingsboard.server.dao.device.DeviceCredentialsService;
|
import org.thingsboard.server.dao.device.DeviceCredentialsService;
|
||||||
|
import org.thingsboard.server.dao.device.DeviceProfileService;
|
||||||
import org.thingsboard.server.dao.device.DeviceProvisionService;
|
import org.thingsboard.server.dao.device.DeviceProvisionService;
|
||||||
import org.thingsboard.server.dao.device.DeviceService;
|
import org.thingsboard.server.dao.device.DeviceService;
|
||||||
import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
|
import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
|
||||||
@ -90,11 +90,15 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRespon
|
|||||||
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos.UpdateOrCreateDeviceX509CertRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceProfileCredentialsResponseMsg;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceProfileX509CertRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
|
||||||
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
|
||||||
|
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
|
||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
|
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
|
||||||
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
|
||||||
@ -108,6 +112,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.thingsboard.server.service.transport.BasicCredentialsValidationResult.PASSWORD_MISMATCH;
|
import static org.thingsboard.server.service.transport.BasicCredentialsValidationResult.PASSWORD_MISMATCH;
|
||||||
@ -128,6 +134,7 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
private final TbTenantProfileCache tenantProfileCache;
|
private final TbTenantProfileCache tenantProfileCache;
|
||||||
private final TbApiUsageStateService apiUsageStateService;
|
private final TbApiUsageStateService apiUsageStateService;
|
||||||
private final DeviceService deviceService;
|
private final DeviceService deviceService;
|
||||||
|
private final DeviceProfileService deviceProfileService;
|
||||||
private final RelationService relationService;
|
private final RelationService relationService;
|
||||||
private final DeviceCredentialsService deviceCredentialsService;
|
private final DeviceCredentialsService deviceCredentialsService;
|
||||||
private final DbCallbackExecutorService dbCallbackExecutorService;
|
private final DbCallbackExecutorService dbCallbackExecutorService;
|
||||||
@ -159,6 +166,13 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
} else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) {
|
} else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) {
|
||||||
ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg();
|
ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg();
|
||||||
result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);
|
result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);
|
||||||
|
} else if (transportApiRequestMsg.hasValidateProfileX509CertRequestMsg()) {
|
||||||
|
ValidateDeviceProfileX509CertRequestMsg msg = transportApiRequestMsg.getValidateProfileX509CertRequestMsg();
|
||||||
|
result = validateDeviceProfileCertificate(msg.getHash());
|
||||||
|
} else if (transportApiRequestMsg.hasUpdateOrCreateDeviceCertRequestMsg()) {
|
||||||
|
UpdateOrCreateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getUpdateOrCreateDeviceCertRequestMsg();
|
||||||
|
DeviceProfile deviceProfile = deviceProfileCache.find(new DeviceProfileId(new UUID(msg.getDeviceProfileIdMSB(), msg.getDeviceProfileIdLSB())));
|
||||||
|
result = updateOrCreateDeviceCredentials(msg.getHash(), msg.getValue(), msg.getCommonName(), deviceProfile, DeviceCredentialsType.X509_CERTIFICATE);
|
||||||
} else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {
|
} else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {
|
||||||
result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());
|
result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());
|
||||||
} else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {
|
} else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {
|
||||||
@ -226,6 +240,31 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ListenableFuture<TransportApiResponseMsg> validateDeviceProfileCertificate(String credentialsId) {
|
||||||
|
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileByCertificateHash(credentialsId);
|
||||||
|
if (deviceProfile != null) {
|
||||||
|
return getDeviceProfileInfo(deviceProfile);
|
||||||
|
}
|
||||||
|
return getEmptyTransportApiResponseFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListenableFuture<TransportApiResponseMsg> updateOrCreateDeviceCredentials(String credentialsId,
|
||||||
|
String credentialsValue,
|
||||||
|
String deviceCN,
|
||||||
|
DeviceProfile deviceProfile,
|
||||||
|
DeviceCredentialsType credentialsType) {
|
||||||
|
String deviceName = extractRegex(deviceCN, deviceProfile.getCertificateRegexPattern());
|
||||||
|
// find deviceCredentials by deviceName (device exists)
|
||||||
|
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByTenantIdAndDeviceName(deviceProfile.getTenantId(), deviceName);
|
||||||
|
if (deviceCredentials != null && deviceCredentials.getCredentialsType() == credentialsType) {
|
||||||
|
deviceCredentials.setCredentialsId(credentialsId);
|
||||||
|
deviceCredentials.setCredentialsValue(credentialsValue);
|
||||||
|
deviceCredentialsService.updateDeviceCredentials(deviceProfile.getTenantId(), deviceCredentials);
|
||||||
|
return getDeviceInfo(deviceCredentials);
|
||||||
|
}
|
||||||
|
return getEmptyTransportApiResponseFuture();
|
||||||
|
}
|
||||||
|
|
||||||
private ListenableFuture<TransportApiResponseMsg> validateUserNameCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) {
|
private ListenableFuture<TransportApiResponseMsg> validateUserNameCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) {
|
||||||
DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName());
|
DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName());
|
||||||
if (credentials != null) {
|
if (credentials != null) {
|
||||||
@ -507,6 +546,18 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
}, MoreExecutors.directExecutor());
|
}, MoreExecutors.directExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ListenableFuture<TransportApiResponseMsg> getDeviceProfileInfo(DeviceProfile deviceProfile) {
|
||||||
|
ValidateDeviceProfileCredentialsResponseMsg.Builder builder = ValidateDeviceProfileCredentialsResponseMsg.newBuilder()
|
||||||
|
.setDeviceProfileIdMSB(deviceProfile.getId().getId().getMostSignificantBits())
|
||||||
|
.setDeviceProfileIdLSB(deviceProfile.getId().getId().getLeastSignificantBits())
|
||||||
|
.setIsDeviceProfileFound(true);
|
||||||
|
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
TransportApiResponseMsg.newBuilder()
|
||||||
|
.setValidateDeviceProfileResponseMsg(builder.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
|
private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
|
||||||
DeviceInfoProto.Builder builder = DeviceInfoProto.newBuilder()
|
DeviceInfoProto.Builder builder = DeviceInfoProto.newBuilder()
|
||||||
.setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
|
.setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
|
||||||
@ -664,4 +715,13 @@ public class DefaultTransportApiService implements TransportApiService {
|
|||||||
private Long checkLong(Long l) {
|
private Long checkLong(Long l) {
|
||||||
return l != null ? l : 0;
|
return l != null ? l : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String extractRegex(String commonName, String regex) {
|
||||||
|
Pattern pattern = Pattern.compile(regex);
|
||||||
|
Matcher matcher = pattern.matcher(commonName);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return matcher.group(0);
|
||||||
|
}
|
||||||
|
return commonName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -169,6 +169,18 @@ message ValidateDeviceX509CertRequestMsg {
|
|||||||
string hash = 1;
|
string hash = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ValidateDeviceProfileX509CertRequestMsg {
|
||||||
|
string hash = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateOrCreateDeviceX509CertRequestMsg {
|
||||||
|
string hash = 1;
|
||||||
|
string value = 2;
|
||||||
|
string commonName = 3;
|
||||||
|
int64 deviceProfileIdMSB = 4;
|
||||||
|
int64 deviceProfileIdLSB = 5;
|
||||||
|
}
|
||||||
|
|
||||||
message ValidateBasicMqttCredRequestMsg {
|
message ValidateBasicMqttCredRequestMsg {
|
||||||
string clientId = 1;
|
string clientId = 1;
|
||||||
string userName = 2;
|
string userName = 2;
|
||||||
@ -181,6 +193,12 @@ message ValidateDeviceCredentialsResponseMsg {
|
|||||||
bytes profileBody = 3;
|
bytes profileBody = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ValidateDeviceProfileCredentialsResponseMsg {
|
||||||
|
int64 deviceProfileIdMSB = 1;
|
||||||
|
int64 deviceProfileIdLSB = 2;
|
||||||
|
bool isDeviceProfileFound = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message GetOrCreateDeviceFromGatewayRequestMsg {
|
message GetOrCreateDeviceFromGatewayRequestMsg {
|
||||||
int64 gatewayIdMSB = 1;
|
int64 gatewayIdMSB = 1;
|
||||||
int64 gatewayIdLSB = 2;
|
int64 gatewayIdLSB = 2;
|
||||||
@ -885,33 +903,36 @@ message VersionControlResponseMsg {
|
|||||||
message TransportApiRequestMsg {
|
message TransportApiRequestMsg {
|
||||||
ValidateDeviceTokenRequestMsg validateTokenRequestMsg = 1;
|
ValidateDeviceTokenRequestMsg validateTokenRequestMsg = 1;
|
||||||
ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2;
|
ValidateDeviceX509CertRequestMsg validateX509CertRequestMsg = 2;
|
||||||
GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 3;
|
ValidateDeviceProfileX509CertRequestMsg validateProfileX509CertRequestMsg = 3;
|
||||||
GetEntityProfileRequestMsg entityProfileRequestMsg = 4;
|
GetOrCreateDeviceFromGatewayRequestMsg getOrCreateDeviceRequestMsg = 4;
|
||||||
LwM2MRequestMsg lwM2MRequestMsg = 5;
|
GetEntityProfileRequestMsg entityProfileRequestMsg = 5;
|
||||||
ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6;
|
LwM2MRequestMsg lwM2MRequestMsg = 6;
|
||||||
ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7;
|
ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 7;
|
||||||
ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8;
|
ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 8;
|
||||||
GetResourceRequestMsg resourceRequestMsg = 9;
|
ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 9;
|
||||||
GetOtaPackageRequestMsg otaPackageRequestMsg = 10;
|
GetResourceRequestMsg resourceRequestMsg = 10;
|
||||||
GetSnmpDevicesRequestMsg snmpDevicesRequestMsg = 11;
|
GetOtaPackageRequestMsg otaPackageRequestMsg = 11;
|
||||||
GetDeviceRequestMsg deviceRequestMsg = 12;
|
GetSnmpDevicesRequestMsg snmpDevicesRequestMsg = 12;
|
||||||
GetDeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 13;
|
GetDeviceRequestMsg deviceRequestMsg = 13;
|
||||||
GetAllQueueRoutingInfoRequestMsg getAllQueueRoutingInfoRequestMsg = 14;
|
GetDeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 14;
|
||||||
|
GetAllQueueRoutingInfoRequestMsg getAllQueueRoutingInfoRequestMsg = 15;
|
||||||
|
UpdateOrCreateDeviceX509CertRequestMsg updateOrCreateDeviceCertRequestMsg = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Response from ThingsBoard Core Service to Transport Service */
|
/* Response from ThingsBoard Core Service to Transport Service */
|
||||||
message TransportApiResponseMsg {
|
message TransportApiResponseMsg {
|
||||||
ValidateDeviceCredentialsResponseMsg validateCredResponseMsg = 1;
|
ValidateDeviceCredentialsResponseMsg validateCredResponseMsg = 1;
|
||||||
GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 2;
|
ValidateDeviceProfileCredentialsResponseMsg validateDeviceProfileResponseMsg = 2;
|
||||||
GetEntityProfileResponseMsg entityProfileResponseMsg = 3;
|
GetOrCreateDeviceFromGatewayResponseMsg getOrCreateDeviceResponseMsg = 3;
|
||||||
ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4;
|
GetEntityProfileResponseMsg entityProfileResponseMsg = 4;
|
||||||
GetSnmpDevicesResponseMsg snmpDevicesResponseMsg = 5;
|
ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 5;
|
||||||
LwM2MResponseMsg lwM2MResponseMsg = 6;
|
GetSnmpDevicesResponseMsg snmpDevicesResponseMsg = 6;
|
||||||
GetResourceResponseMsg resourceResponseMsg = 7;
|
LwM2MResponseMsg lwM2MResponseMsg = 7;
|
||||||
GetOtaPackageResponseMsg otaPackageResponseMsg = 8;
|
GetResourceResponseMsg resourceResponseMsg = 8;
|
||||||
GetDeviceResponseMsg deviceResponseMsg = 9;
|
GetOtaPackageResponseMsg otaPackageResponseMsg = 9;
|
||||||
GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 10;
|
GetDeviceResponseMsg deviceResponseMsg = 10;
|
||||||
repeated GetQueueRoutingInfoResponseMsg getQueueRoutingInfoResponseMsgs = 11;
|
GetDeviceCredentialsResponseMsg deviceCredentialsResponseMsg = 11;
|
||||||
|
repeated GetQueueRoutingInfoResponseMsg getQueueRoutingInfoResponseMsgs = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Messages that are handled by ThingsBoard Core Service */
|
/* Messages that are handled by ThingsBoard Core Service */
|
||||||
|
|||||||
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.dao.device;
|
package org.thingsboard.server.dao.device;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
|
|
||||||
public interface DeviceCredentialsService {
|
public interface DeviceCredentialsService {
|
||||||
|
|
||||||
@ -26,6 +26,8 @@ public interface DeviceCredentialsService {
|
|||||||
|
|
||||||
DeviceCredentials findDeviceCredentialsByCredentialsId(String credentialsId);
|
DeviceCredentials findDeviceCredentialsByCredentialsId(String credentialsId);
|
||||||
|
|
||||||
|
DeviceCredentials findDeviceCredentialsByTenantIdAndDeviceName(TenantId tenantId, String deviceName);
|
||||||
|
|
||||||
DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
|
DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
|
||||||
|
|
||||||
DeviceCredentials createDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
|
DeviceCredentials createDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials);
|
||||||
|
|||||||
@ -39,6 +39,8 @@ public interface DeviceProfileService extends EntityDaoService {
|
|||||||
|
|
||||||
PageData<DeviceProfileInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink, String transportType);
|
PageData<DeviceProfileInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink, String transportType);
|
||||||
|
|
||||||
|
DeviceProfile findDeviceProfileByCertificateHash(String credentialsId);
|
||||||
|
|
||||||
DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String profileName);
|
DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String profileName);
|
||||||
|
|
||||||
DeviceProfile createDefaultDeviceProfile(TenantId tenantId);
|
DeviceProfile createDefaultDeviceProfile(TenantId tenantId);
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
package org.thingsboard.server.common.data;
|
package org.thingsboard.server.common.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
@ -28,7 +27,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
|
|||||||
import org.thingsboard.server.common.data.id.DashboardId;
|
import org.thingsboard.server.common.data.id.DashboardId;
|
||||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||||
import org.thingsboard.server.common.data.id.OtaPackageId;
|
import org.thingsboard.server.common.data.id.OtaPackageId;
|
||||||
import org.thingsboard.server.common.data.id.QueueId;
|
|
||||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.validation.Length;
|
import org.thingsboard.server.common.data.validation.Length;
|
||||||
@ -68,6 +66,13 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H
|
|||||||
private DeviceTransportType transportType;
|
private DeviceTransportType transportType;
|
||||||
@ApiModelProperty(position = 15, value = "Provisioning strategy.")
|
@ApiModelProperty(position = 15, value = "Provisioning strategy.")
|
||||||
private DeviceProfileProvisionType provisionType;
|
private DeviceProfileProvisionType provisionType;
|
||||||
|
@ApiModelProperty(position = 16, value = "CA certificate value")
|
||||||
|
private String certificateValue;
|
||||||
|
@ApiModelProperty(position = 17, value = "CA certificate hash")
|
||||||
|
private String certificateHash;
|
||||||
|
@ApiModelProperty(position = 18, value = "Regex for fetch deviceName from CN")
|
||||||
|
private String certificateRegexPattern;
|
||||||
|
|
||||||
@ApiModelProperty(position = 7, value = "Reference to the rule chain. " +
|
@ApiModelProperty(position = 7, value = "Reference to the rule chain. " +
|
||||||
"If present, the specified rule chain will be used to process all messages related to device, including telemetry, attribute updates, etc. " +
|
"If present, the specified rule chain will be used to process all messages related to device, including telemetry, attribute updates, etc. " +
|
||||||
"Otherwise, the root rule chain will be used to process those messages.")
|
"Otherwise, the root rule chain will be used to process those messages.")
|
||||||
|
|||||||
@ -24,12 +24,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
|
||||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
import org.thingsboard.server.common.msg.EncryptionUtil;
|
import org.thingsboard.server.common.msg.EncryptionUtil;
|
||||||
import org.thingsboard.server.common.transport.TransportService;
|
import org.thingsboard.server.common.transport.TransportService;
|
||||||
import org.thingsboard.server.common.transport.TransportServiceCallback;
|
import org.thingsboard.server.common.transport.TransportServiceCallback;
|
||||||
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
||||||
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceProfileCredentialsResponse;
|
||||||
import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
|
import org.thingsboard.server.common.transport.config.ssl.SslCredentials;
|
||||||
import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
|
import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig;
|
||||||
import org.thingsboard.server.common.transport.util.SslUtil;
|
import org.thingsboard.server.common.transport.util.SslUtil;
|
||||||
@ -142,8 +143,15 @@ public class MqttSslHandlerProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkClientTrusted(X509Certificate[] chain,
|
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
String authType) throws CertificateException {
|
String deviceCN = SslUtil.parseCommonName(chain[0]);
|
||||||
|
String deviceCert;
|
||||||
|
String deviceCredentialsValue = SslUtil.getCertificateString(chain[0]);
|
||||||
|
try {
|
||||||
|
deviceCert = EncryptionUtil.getSha3Hash(SslUtil.getCertificateString(chain[0]));
|
||||||
|
} catch (CertificateEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
String credentialsBody = null;
|
String credentialsBody = null;
|
||||||
for (X509Certificate cert : chain) {
|
for (X509Certificate cert : chain) {
|
||||||
try {
|
try {
|
||||||
@ -152,13 +160,53 @@ public class MqttSslHandlerProvider {
|
|||||||
final String[] credentialsBodyHolder = new String[1];
|
final String[] credentialsBodyHolder = new String[1];
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
transportService.process(DeviceTransportType.MQTT, TransportProtos.ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),
|
transportService.process(DeviceTransportType.MQTT, TransportProtos.ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),
|
||||||
new TransportServiceCallback<ValidateDeviceCredentialsResponse>() {
|
new TransportServiceCallback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(ValidateDeviceCredentialsResponse msg) {
|
public void onSuccess(ValidateDeviceCredentialsResponse msg) {
|
||||||
if (!StringUtils.isEmpty(msg.getCredentials())) {
|
if (!StringUtils.isEmpty(msg.getCredentials())) {
|
||||||
credentialsBodyHolder[0] = msg.getCredentials();
|
credentialsBodyHolder[0] = msg.getCredentials();
|
||||||
|
latch.countDown();
|
||||||
|
} else {
|
||||||
|
transportService.process(DeviceTransportType.MQTT,
|
||||||
|
TransportProtos.ValidateDeviceProfileX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),
|
||||||
|
new TransportServiceCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ValidateDeviceProfileCredentialsResponse msg) {
|
||||||
|
if (msg.isDeviceProfileFound()) {
|
||||||
|
transportService.process(DeviceTransportType.MQTT,
|
||||||
|
TransportProtos.UpdateOrCreateDeviceX509CertRequestMsg.newBuilder()
|
||||||
|
.setHash(deviceCert)
|
||||||
|
.setCommonName(deviceCN)
|
||||||
|
.setDeviceProfileIdMSB(msg.getDeviceProfileId().getId().getMostSignificantBits())
|
||||||
|
.setDeviceProfileIdLSB(msg.getDeviceProfileId().getId().getLeastSignificantBits())
|
||||||
|
.build(),
|
||||||
|
new TransportServiceCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ValidateDeviceCredentialsResponse msg) {
|
||||||
|
System.out.println("msg.getCredentials() = " + msg.getCredentials());
|
||||||
|
credentialsBodyHolder[0] = msg.getCredentials();
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
latch.countDown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -168,7 +216,7 @@ public class MqttSslHandlerProvider {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
latch.await(10, TimeUnit.SECONDS);
|
latch.await(10, TimeUnit.SECONDS);
|
||||||
if (strCert.equals(credentialsBodyHolder[0])) {
|
if (deviceCredentialsValue.equals(credentialsBodyHolder[0])) {
|
||||||
credentialsBody = credentialsBodyHolder[0];
|
credentialsBody = credentialsBodyHolder[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import io.netty.channel.ChannelFuture;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.handler.codec.mqtt.MqttConnAckMessage;
|
import io.netty.handler.codec.mqtt.MqttConnAckMessage;
|
||||||
import io.netty.handler.codec.mqtt.MqttConnAckVariableHeader;
|
|
||||||
import io.netty.handler.codec.mqtt.MqttConnectMessage;
|
import io.netty.handler.codec.mqtt.MqttConnectMessage;
|
||||||
import io.netty.handler.codec.mqtt.MqttConnectReturnCode;
|
import io.netty.handler.codec.mqtt.MqttConnectReturnCode;
|
||||||
import io.netty.handler.codec.mqtt.MqttFixedHeader;
|
import io.netty.handler.codec.mqtt.MqttFixedHeader;
|
||||||
@ -63,12 +62,12 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException;
|
|||||||
import org.thingsboard.server.common.transport.auth.SessionInfoCreator;
|
import org.thingsboard.server.common.transport.auth.SessionInfoCreator;
|
||||||
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
|
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
|
||||||
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
||||||
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceProfileCredentialsResponse;
|
||||||
import org.thingsboard.server.common.transport.service.DefaultTransportService;
|
import org.thingsboard.server.common.transport.service.DefaultTransportService;
|
||||||
import org.thingsboard.server.common.transport.service.SessionMetaData;
|
import org.thingsboard.server.common.transport.service.SessionMetaData;
|
||||||
import org.thingsboard.server.common.transport.util.SslUtil;
|
import org.thingsboard.server.common.transport.util.SslUtil;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
|
|
||||||
import org.thingsboard.server.queue.scheduler.SchedulerComponent;
|
import org.thingsboard.server.queue.scheduler.SchedulerComponent;
|
||||||
import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
|
import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor;
|
||||||
import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx;
|
import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx;
|
||||||
@ -80,7 +79,7 @@ import org.thingsboard.server.transport.mqtt.util.ReturnCodeResolver;
|
|||||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -90,16 +89,15 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static com.amazonaws.util.StringUtils.UTF8;
|
import static com.amazonaws.util.StringUtils.UTF8;
|
||||||
import static io.netty.handler.codec.mqtt.MqttMessageType.CONNACK;
|
|
||||||
import static io.netty.handler.codec.mqtt.MqttMessageType.CONNECT;
|
import static io.netty.handler.codec.mqtt.MqttMessageType.CONNECT;
|
||||||
import static io.netty.handler.codec.mqtt.MqttMessageType.PINGRESP;
|
import static io.netty.handler.codec.mqtt.MqttMessageType.PINGRESP;
|
||||||
import static io.netty.handler.codec.mqtt.MqttMessageType.SUBACK;
|
import static io.netty.handler.codec.mqtt.MqttMessageType.SUBACK;
|
||||||
import static io.netty.handler.codec.mqtt.MqttMessageType.UNSUBACK;
|
|
||||||
import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE;
|
import static io.netty.handler.codec.mqtt.MqttQoS.AT_LEAST_ONCE;
|
||||||
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
|
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;
|
||||||
import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED;
|
import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED;
|
||||||
@ -810,9 +808,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
|
|||||||
deviceSessionCtx.setProvisionOnly(true);
|
deviceSessionCtx.setProvisionOnly(true);
|
||||||
ctx.writeAndFlush(createMqttConnAckMsg(ReturnCode.SUCCESS, msg));
|
ctx.writeAndFlush(createMqttConnAckMsg(ReturnCode.SUCCESS, msg));
|
||||||
} else {
|
} else {
|
||||||
X509Certificate cert;
|
X509Certificate[] chain;
|
||||||
if (sslHandler != null && (cert = getX509Certificate()) != null) {
|
if (sslHandler != null && (chain = getX509Certificate()) != null) {
|
||||||
processX509CertConnect(ctx, cert, msg);
|
processX509CertConnect(ctx, chain, msg);
|
||||||
} else {
|
} else {
|
||||||
processAuthTokenConnect(ctx, msg);
|
processAuthTokenConnect(ctx, msg);
|
||||||
}
|
}
|
||||||
@ -848,27 +846,82 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate cert, MqttConnectMessage connectMessage) {
|
private void processX509CertConnect(ChannelHandlerContext ctx, X509Certificate[] chain, MqttConnectMessage connectMessage) {
|
||||||
try {
|
try {
|
||||||
if (!context.isSkipValidityCheckForClientCert()) {
|
String deviceCN = SslUtil.parseCommonName(chain[0]);
|
||||||
cert.checkValidity();
|
String deviceCertHash = EncryptionUtil.getSha3Hash(SslUtil.getCertificateString(chain[0]));
|
||||||
}
|
for (X509Certificate cert : chain) {
|
||||||
String strCert = SslUtil.getCertificateString(cert);
|
try {
|
||||||
String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
|
String strCert = SslUtil.getCertificateString(cert);
|
||||||
transportService.process(DeviceTransportType.MQTT, ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),
|
String sha3Hash = EncryptionUtil.getSha3Hash(strCert);
|
||||||
new TransportServiceCallback<>() {
|
final ValidateDeviceCredentialsResponse[] validateDeviceCredentialsResponses = new ValidateDeviceCredentialsResponse[1];
|
||||||
@Override
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
public void onSuccess(ValidateDeviceCredentialsResponse msg) {
|
transportService.process(DeviceTransportType.MQTT, TransportProtos.ValidateDeviceX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),
|
||||||
onValidateDeviceResponse(msg, ctx, connectMessage);
|
new TransportServiceCallback<>() {
|
||||||
}
|
@Override
|
||||||
|
public void onSuccess(ValidateDeviceCredentialsResponse msg) {
|
||||||
|
if (!StringUtils.isEmpty(msg.getCredentials())) {
|
||||||
|
validateDeviceCredentialsResponses[0] = msg;
|
||||||
|
latch.countDown();
|
||||||
|
} else {
|
||||||
|
transportService.process(DeviceTransportType.MQTT,
|
||||||
|
TransportProtos.ValidateDeviceProfileX509CertRequestMsg.newBuilder().setHash(sha3Hash).build(),
|
||||||
|
new TransportServiceCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ValidateDeviceProfileCredentialsResponse msg) {
|
||||||
|
if (msg.isDeviceProfileFound()) {
|
||||||
|
transportService.process(DeviceTransportType.MQTT,
|
||||||
|
TransportProtos.UpdateOrCreateDeviceX509CertRequestMsg.newBuilder()
|
||||||
|
.setHash(deviceCertHash)
|
||||||
|
.setCommonName(deviceCN)
|
||||||
|
.setDeviceProfileIdMSB(msg.getDeviceProfileId().getId().getMostSignificantBits())
|
||||||
|
.setDeviceProfileIdLSB(msg.getDeviceProfileId().getId().getLeastSignificantBits())
|
||||||
|
.build(),
|
||||||
|
new TransportServiceCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ValidateDeviceCredentialsResponse msg) {
|
||||||
|
if (!StringUtils.isEmpty(msg.getCredentials())) {
|
||||||
|
validateDeviceCredentialsResponses[0] = msg;
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable e) {
|
public void onError(Throwable e) {
|
||||||
log.trace("[{}] Failed to process credentials: {}", address, sha3Hash, e);
|
log.error(e.getMessage(), e);
|
||||||
ctx.writeAndFlush(createMqttConnAckMsg(ReturnCode.SERVER_UNAVAILABLE_5, connectMessage));
|
latch.countDown();
|
||||||
ctx.close();
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
} else {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
latch.await(10, TimeUnit.SECONDS);
|
||||||
|
if (validateDeviceCredentialsResponses[0] != null && validateDeviceCredentialsResponses[0].hasDeviceInfo()) {
|
||||||
|
onValidateDeviceResponse(validateDeviceCredentialsResponses[0], ctx, connectMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | CertificateEncodingException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
context.onAuthFailure(address);
|
context.onAuthFailure(address);
|
||||||
ctx.writeAndFlush(createMqttConnAckMsg(ReturnCode.NOT_AUTHORIZED_5, connectMessage));
|
ctx.writeAndFlush(createMqttConnAckMsg(ReturnCode.NOT_AUTHORIZED_5, connectMessage));
|
||||||
@ -877,17 +930,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private X509Certificate getX509Certificate() {
|
private X509Certificate[] getX509Certificate() {
|
||||||
try {
|
try {
|
||||||
Certificate[] certChain = sslHandler.engine().getSession().getPeerCertificates();
|
return (X509Certificate[]) sslHandler.engine().getSession().getPeerCertificates();
|
||||||
if (certChain.length > 0) {
|
|
||||||
return (X509Certificate) certChain[0];
|
|
||||||
}
|
|
||||||
} catch (SSLPeerUnverifiedException e) {
|
} catch (SSLPeerUnverifiedException e) {
|
||||||
log.warn(e.getMessage());
|
log.warn(e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MqttConnAckMessage createMqttConnAckMsg(ReturnCode returnCode, MqttConnectMessage msg) {
|
private MqttConnAckMessage createMqttConnAckMsg(ReturnCode returnCode, MqttConnectMessage msg) {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
|
|||||||
import org.thingsboard.server.common.data.rpc.RpcStatus;
|
import org.thingsboard.server.common.data.rpc.RpcStatus;
|
||||||
import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse;
|
import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse;
|
||||||
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
||||||
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceProfileCredentialsResponse;
|
||||||
import org.thingsboard.server.common.transport.service.SessionMetaData;
|
import org.thingsboard.server.common.transport.service.SessionMetaData;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg;
|
||||||
@ -52,8 +53,10 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMs
|
|||||||
import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos.UpdateOrCreateDeviceX509CertRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCredRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCredRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
|
||||||
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceProfileX509CertRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
|
||||||
|
|
||||||
@ -87,6 +90,12 @@ public interface TransportService {
|
|||||||
void process(DeviceTransportType transportType, ValidateDeviceX509CertRequestMsg msg,
|
void process(DeviceTransportType transportType, ValidateDeviceX509CertRequestMsg msg,
|
||||||
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
|
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
|
||||||
|
|
||||||
|
void process(DeviceTransportType transportType, ValidateDeviceProfileX509CertRequestMsg msg,
|
||||||
|
TransportServiceCallback<ValidateDeviceProfileCredentialsResponse> callback);
|
||||||
|
|
||||||
|
void process(DeviceTransportType transportType, UpdateOrCreateDeviceX509CertRequestMsg msg,
|
||||||
|
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
|
||||||
|
|
||||||
void process(ValidateDeviceLwM2MCredentialsRequestMsg msg,
|
void process(ValidateDeviceLwM2MCredentialsRequestMsg msg,
|
||||||
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
|
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.common.transport.auth;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class ValidateDeviceProfileCredentialsResponse {
|
||||||
|
|
||||||
|
private final DeviceProfileId deviceProfileId;
|
||||||
|
private final boolean isDeviceProfileFound;
|
||||||
|
}
|
||||||
@ -71,8 +71,8 @@ import org.thingsboard.server.common.transport.TransportTenantProfileCache;
|
|||||||
import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse;
|
import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse;
|
||||||
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
|
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
|
||||||
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
|
||||||
|
import org.thingsboard.server.common.transport.auth.ValidateDeviceProfileCredentialsResponse;
|
||||||
import org.thingsboard.server.common.transport.limits.TransportRateLimitService;
|
import org.thingsboard.server.common.transport.limits.TransportRateLimitService;
|
||||||
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
|
|
||||||
import org.thingsboard.server.common.transport.util.JsonUtils;
|
import org.thingsboard.server.common.transport.util.JsonUtils;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos;
|
import org.thingsboard.server.gen.transport.TransportProtos;
|
||||||
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
|
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
|
||||||
@ -97,6 +97,7 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
|
|||||||
import org.thingsboard.server.queue.provider.TbTransportQueueFactory;
|
import org.thingsboard.server.queue.provider.TbTransportQueueFactory;
|
||||||
import org.thingsboard.server.queue.scheduler.SchedulerComponent;
|
import org.thingsboard.server.queue.scheduler.SchedulerComponent;
|
||||||
import org.thingsboard.server.queue.util.AfterStartUp;
|
import org.thingsboard.server.queue.util.AfterStartUp;
|
||||||
|
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
|
||||||
import org.thingsboard.server.queue.util.TbTransportComponent;
|
import org.thingsboard.server.queue.util.TbTransportComponent;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
@ -427,6 +428,32 @@ public class DefaultTransportService implements TransportService {
|
|||||||
AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);
|
AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceProfileX509CertRequestMsg requestMsg,
|
||||||
|
TransportServiceCallback<ValidateDeviceProfileCredentialsResponse> callback) {
|
||||||
|
log.trace("Processing msg: {}", requestMsg);
|
||||||
|
TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(),
|
||||||
|
TransportApiRequestMsg.newBuilder().setValidateProfileX509CertRequestMsg(requestMsg).build());
|
||||||
|
ListenableFuture<ValidateDeviceProfileCredentialsResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> {
|
||||||
|
TransportProtos.ValidateDeviceProfileCredentialsResponseMsg msg = tmp.getValue().getValidateDeviceProfileResponseMsg();
|
||||||
|
ValidateDeviceProfileCredentialsResponse.ValidateDeviceProfileCredentialsResponseBuilder result = ValidateDeviceProfileCredentialsResponse.builder();
|
||||||
|
DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(msg.getDeviceProfileIdMSB(), msg.getDeviceProfileIdLSB()));
|
||||||
|
result.deviceProfileId(deviceProfileId);
|
||||||
|
result.isDeviceProfileFound(msg.getIsDeviceProfileFound());
|
||||||
|
return result.build();
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(DeviceTransportType transportType, TransportProtos.UpdateOrCreateDeviceX509CertRequestMsg requestMsg,
|
||||||
|
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
|
||||||
|
log.trace("Processing msg: {}", requestMsg);
|
||||||
|
TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder()
|
||||||
|
.setUpdateOrCreateDeviceCertRequestMsg(requestMsg).build());
|
||||||
|
doProcess(transportType, protoMsg, callback);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceX509CertRequestMsg msg, TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
|
public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceX509CertRequestMsg msg, TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
|
||||||
log.trace("Processing msg: {}", msg);
|
log.trace("Processing msg: {}", msg);
|
||||||
|
|||||||
@ -16,11 +16,17 @@
|
|||||||
package org.thingsboard.server.common.transport.util;
|
package org.thingsboard.server.common.transport.util;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.bouncycastle.asn1.x500.RDN;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||||
|
import org.bouncycastle.asn1.x500.style.IETFUtils;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
|
||||||
import org.springframework.util.Base64Utils;
|
import org.springframework.util.Base64Utils;
|
||||||
import org.thingsboard.server.common.msg.EncryptionUtil;
|
import org.thingsboard.server.common.msg.EncryptionUtil;
|
||||||
|
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Valerii Sosliuk
|
* @author Valerii Sosliuk
|
||||||
@ -35,4 +41,15 @@ public class SslUtil {
|
|||||||
throws CertificateEncodingException {
|
throws CertificateEncodingException {
|
||||||
return EncryptionUtil.certTrimNewLines(Base64Utils.encodeToString(cert.getEncoded()));
|
return EncryptionUtil.certTrimNewLines(Base64Utils.encodeToString(cert.getEncoded()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String parseCommonName(X509Certificate certificate) {
|
||||||
|
X500Name x500name;
|
||||||
|
try {
|
||||||
|
x500name = new JcaX509CertificateHolder(certificate).getSubject();
|
||||||
|
} catch (CertificateEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
RDN cn = x500name.getRDNs(BCStyle.CN)[0];
|
||||||
|
return IETFUtils.valueToString(cn.getFirst().getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,4 +53,12 @@ public interface DeviceCredentialsDao extends Dao<DeviceCredentials> {
|
|||||||
*/
|
*/
|
||||||
DeviceCredentials findByCredentialsId(TenantId tenantId, String credentialsId);
|
DeviceCredentials findByCredentialsId(TenantId tenantId, String credentialsId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find device credentials by device name.
|
||||||
|
*
|
||||||
|
* @param deviceName the device name
|
||||||
|
* @return the device credentials object
|
||||||
|
*/
|
||||||
|
DeviceCredentials findByTenantIdAndDeviceName(TenantId tenantId, String deviceName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,15 +16,12 @@
|
|||||||
package org.thingsboard.server.dao.device;
|
package org.thingsboard.server.dao.device;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
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.SecurityUtil;
|
import org.eclipse.leshan.core.util.SecurityUtil;
|
||||||
import org.hibernate.exception.ConstraintViolationException;
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.transaction.event.TransactionalEventListener;
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
@ -86,6 +83,13 @@ public class DeviceCredentialsServiceImpl extends AbstractCachedEntityService<St
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceCredentials findDeviceCredentialsByTenantIdAndDeviceName(TenantId tenantId, String deviceName) {
|
||||||
|
log.trace("Executing findDeviceCredentialsByDeviceName [{}]", deviceName);
|
||||||
|
validateString(deviceName, "Incorrect deviceName " + deviceName);
|
||||||
|
return deviceCredentialsDao.findByTenantIdAndDeviceName(tenantId, deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials) {
|
public DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials) {
|
||||||
return saveOrUpdate(tenantId, deviceCredentials);
|
return saveOrUpdate(tenantId, deviceCredentials);
|
||||||
|
|||||||
@ -29,25 +29,31 @@ public class DeviceProfileCacheKey implements Serializable {
|
|||||||
private final TenantId tenantId;
|
private final TenantId tenantId;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final DeviceProfileId deviceProfileId;
|
private final DeviceProfileId deviceProfileId;
|
||||||
|
private final String certificateHash;
|
||||||
private final boolean defaultProfile;
|
private final boolean defaultProfile;
|
||||||
|
|
||||||
private DeviceProfileCacheKey(TenantId tenantId, String name, DeviceProfileId deviceProfileId, boolean defaultProfile) {
|
private DeviceProfileCacheKey(TenantId tenantId, String name, DeviceProfileId deviceProfileId, String certificateHash, boolean defaultProfile) {
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.deviceProfileId = deviceProfileId;
|
this.deviceProfileId = deviceProfileId;
|
||||||
|
this.certificateHash = certificateHash;
|
||||||
this.defaultProfile = defaultProfile;
|
this.defaultProfile = defaultProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeviceProfileCacheKey fromName(TenantId tenantId, String name) {
|
public static DeviceProfileCacheKey fromName(TenantId tenantId, String name) {
|
||||||
return new DeviceProfileCacheKey(tenantId, name, null, false);
|
return new DeviceProfileCacheKey(tenantId, name, null, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeviceProfileCacheKey fromId(DeviceProfileId id) {
|
public static DeviceProfileCacheKey fromId(DeviceProfileId id) {
|
||||||
return new DeviceProfileCacheKey(null, null, id, false);
|
return new DeviceProfileCacheKey(null, null, id, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DeviceProfileCacheKey fromCertificateHash(String certificateHash) {
|
||||||
|
return new DeviceProfileCacheKey(null, null, null, certificateHash, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeviceProfileCacheKey defaultProfile(TenantId tenantId) {
|
public static DeviceProfileCacheKey defaultProfile(TenantId tenantId) {
|
||||||
return new DeviceProfileCacheKey(tenantId, null, null, true);
|
return new DeviceProfileCacheKey(tenantId, null, null, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -45,4 +45,6 @@ public interface DeviceProfileDao extends Dao<DeviceProfile>, ExportableEntityDa
|
|||||||
DeviceProfile findByProvisionDeviceKey(String provisionDeviceKey);
|
DeviceProfile findByProvisionDeviceKey(String provisionDeviceKey);
|
||||||
|
|
||||||
DeviceProfile findByName(TenantId tenantId, String profileName);
|
DeviceProfile findByName(TenantId tenantId, String profileName);
|
||||||
|
|
||||||
|
DeviceProfile findByCertificateHash(String certificateHash);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,7 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.thingsboard.server.dao.service.Validator.validateId;
|
import static org.thingsboard.server.dao.service.Validator.validateId;
|
||||||
|
import static org.thingsboard.server.dao.service.Validator.validateString;
|
||||||
|
|
||||||
@Service("DeviceProfileDaoService")
|
@Service("DeviceProfileDaoService")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -61,6 +62,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
|
|||||||
private static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
private static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
|
||||||
private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId ";
|
private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId ";
|
||||||
private static final String INCORRECT_DEVICE_PROFILE_NAME = "Incorrect deviceProfileName ";
|
private static final String INCORRECT_DEVICE_PROFILE_NAME = "Incorrect deviceProfileName ";
|
||||||
|
private static final String INCORRECT_DEVICE_PROFILE_CREDENTIALS_HASH = "Incorrect deviceProfileCredentialsHash ";
|
||||||
private static final String DEVICE_PROFILE_WITH_SUCH_NAME_ALREADY_EXISTS = "Device profile with such name already exists!";
|
private static final String DEVICE_PROFILE_WITH_SUCH_NAME_ALREADY_EXISTS = "Device profile with such name already exists!";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -197,6 +199,14 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
|
|||||||
return deviceProfileDao.findDeviceProfileInfos(tenantId, pageLink, transportType);
|
return deviceProfileDao.findDeviceProfileInfos(tenantId, pageLink, transportType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceProfile findDeviceProfileByCertificateHash(String certificateHash) {
|
||||||
|
log.trace("Executing findDeviceProfileIdByCredentialsId credentialId [{}]", certificateHash);
|
||||||
|
validateString(certificateHash, INCORRECT_DEVICE_PROFILE_CREDENTIALS_HASH + certificateHash);
|
||||||
|
return cache.getAndPutInTransaction(DeviceProfileCacheKey.fromCertificateHash(certificateHash),
|
||||||
|
() -> deviceProfileDao.findByCertificateHash(certificateHash), true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String name) {
|
public DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String name) {
|
||||||
log.trace("Executing findOrCreateDefaultDeviceProfile");
|
log.trace("Executing findOrCreateDefaultDeviceProfile");
|
||||||
|
|||||||
@ -16,6 +16,8 @@
|
|||||||
package org.thingsboard.server.dao.sql.device;
|
package org.thingsboard.server.dao.sql.device;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.thingsboard.server.dao.model.sql.DeviceCredentialsEntity;
|
import org.thingsboard.server.dao.model.sql.DeviceCredentialsEntity;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -28,4 +30,7 @@ public interface DeviceCredentialsRepository extends JpaRepository<DeviceCredent
|
|||||||
DeviceCredentialsEntity findByDeviceId(UUID deviceId);
|
DeviceCredentialsEntity findByDeviceId(UUID deviceId);
|
||||||
|
|
||||||
DeviceCredentialsEntity findByCredentialsId(String credentialsId);
|
DeviceCredentialsEntity findByCredentialsId(String credentialsId);
|
||||||
|
|
||||||
|
@Query("SELECT dc FROM DeviceCredentialsEntity dc INNER JOIN DeviceEntity de ON dc.deviceId = de.id WHERE de.tenantId = :tenantId AND de.name = :deviceName ")
|
||||||
|
DeviceCredentialsEntity findByTenantIdAndDeviceName(@Param("tenantId") UUID tenantId, @Param("deviceName") String deviceName);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,8 @@ public interface DeviceProfileRepository extends JpaRepository<DeviceProfileEnti
|
|||||||
"WHERE d.tenantId = :tenantId AND d.isDefault = true")
|
"WHERE d.tenantId = :tenantId AND d.isDefault = true")
|
||||||
DeviceProfileInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId);
|
DeviceProfileInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId);
|
||||||
|
|
||||||
|
DeviceProfileEntity findDeviceProfileByCertificateHash(String certificateHash);
|
||||||
|
|
||||||
DeviceProfileEntity findByTenantIdAndName(UUID id, String profileName);
|
DeviceProfileEntity findByTenantIdAndName(UUID id, String profileName);
|
||||||
|
|
||||||
DeviceProfileEntity findByProvisionDeviceKey(@Param("provisionDeviceKey") String provisionDeviceKey);
|
DeviceProfileEntity findByProvisionDeviceKey(@Param("provisionDeviceKey") String provisionDeviceKey);
|
||||||
|
|||||||
@ -66,4 +66,9 @@ public class JpaDeviceCredentialsDao extends JpaAbstractDao<DeviceCredentialsEnt
|
|||||||
public DeviceCredentials findByCredentialsId(TenantId tenantId, String credentialsId) {
|
public DeviceCredentials findByCredentialsId(TenantId tenantId, String credentialsId) {
|
||||||
return DaoUtil.getData(deviceCredentialsRepository.findByCredentialsId(credentialsId));
|
return DaoUtil.getData(deviceCredentialsRepository.findByCredentialsId(credentialsId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceCredentials findByTenantIdAndDeviceName(TenantId tenantId, String deviceName) {
|
||||||
|
return DaoUtil.getData(deviceCredentialsRepository.findByTenantIdAndDeviceName(tenantId, deviceName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -115,6 +115,11 @@ public class JpaDeviceProfileDao extends JpaAbstractSearchTextDao<DeviceProfileE
|
|||||||
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndName(tenantId.getId(), profileName));
|
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndName(tenantId.getId(), profileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceProfile findByCertificateHash(String certificateHash) {
|
||||||
|
return DaoUtil.getData(deviceProfileRepository.findDeviceProfileByCertificateHash(certificateHash));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeviceProfile findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
|
public DeviceProfile findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
|
||||||
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user