Browse Source

Refactoring: fix conflict, add logs

pull/7935/head
Andrii Landiak 3 years ago
parent
commit
2ac861876e
  1. 3
      application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java
  2. 77
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  3. 8
      application/src/main/resources/thingsboard.yml
  4. 17
      application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java
  5. 7
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/X509CertificateChainProvisionConfiguration.java
  6. 10
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java
  7. 1
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java
  8. 22
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

3
application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java

@ -82,6 +82,9 @@ public class DefaultCacheCleanupService implements CacheCleanupService {
log.info("Clearing cache to upgrade from version 3.4.2 to 3.4.3 ..."); log.info("Clearing cache to upgrade from version 3.4.2 to 3.4.3 ...");
clearCacheByName("repositorySettings"); clearCacheByName("repositorySettings");
break; break;
case "3.4.4":
log.info("Clearing cache to upgrade from version 3.4.4 to 3.5.0");
clearCacheByName("deviceProfiles");
default: default:
//Do nothing, since cache cleanup is optional. //Do nothing, since cache cleanup is optional.
} }

77
application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java

@ -174,7 +174,7 @@ public class DefaultTransportApiService implements TransportApiService {
result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE); result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);
} else if (transportApiRequestMsg.hasValidateOrCreateX509CertRequestMsg()) { } else if (transportApiRequestMsg.hasValidateOrCreateX509CertRequestMsg()) {
TransportProtos.ValidateOrCreateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateOrCreateX509CertRequestMsg(); TransportProtos.ValidateOrCreateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateOrCreateX509CertRequestMsg();
result = validateOrCreateDeviceX509Certificate(msg.getCertificateChain(), DeviceCredentialsType.X509_CERTIFICATE); result = validateOrCreateDeviceX509Certificate(msg.getCertificateChain());
} else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) { } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {
result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg()); result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());
} else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {
@ -242,19 +242,12 @@ public class DefaultTransportApiService implements TransportApiService {
} }
} }
protected ListenableFuture<TransportApiResponseMsg> validateOrCreateDeviceX509Certificate(String certChain, DeviceCredentialsType credentialsType) { protected ListenableFuture<TransportApiResponseMsg> validateOrCreateDeviceX509Certificate(String certChain) {
List<String> chain = convertX509CertificateChainToList(certChain); List<String> chain = convertX509CertificateChainToList(certChain);
String updateDeviceCertificateValue = chain.get(0);
String updateDeviceCertificateHash = EncryptionUtil.getSha3Hash(updateDeviceCertificateValue);
String deviceCommonName = "";
try {
deviceCommonName = SslUtil.parseCommonName(readCertFile(chain.get(0)));
} catch (Exception ignored) {
}
for (String certificateValue : chain) { for (String certificateValue : chain) {
String certificateHash = EncryptionUtil.getSha3Hash(certificateValue); String certificateHash = EncryptionUtil.getSha3Hash(certificateValue);
DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(certificateHash); DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(certificateHash);
if (credentials != null && credentials.getCredentialsType() == credentialsType) { if (credentials != null && credentials.getCredentialsType() == DeviceCredentialsType.X509_CERTIFICATE) {
return getDeviceInfo(credentials); return getDeviceInfo(credentials);
} }
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileByCertificateHash(certificateHash); DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileByCertificateHash(certificateHash);
@ -262,26 +255,31 @@ public class DefaultTransportApiService implements TransportApiService {
X509CertificateChainProvisionConfiguration x509Configuration = new X509CertificateChainProvisionConfiguration(); X509CertificateChainProvisionConfiguration x509Configuration = new X509CertificateChainProvisionConfiguration();
if (deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) { if (deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) {
x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration(); x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration();
} else {
log.warn("Device Profile provision configuration is not X509CertificateChainProvisionConfiguration");
} }
String deviceName = extractDeviceNameFromCNByRegEx(deviceCommonName, x509Configuration.getCertificateRegExPattern()); String deviceName = extractDeviceNameFromCertificateCNByRegEx(chain.get(0), x509Configuration.getCertificateRegExPattern());
if (deviceName == null) { if (deviceName == null) {
log.error("Device name cannot be unmatched from CN!"); log.warn("Device name has to be extract by regex from CN.");
return getEmptyTransportApiResponseFuture();
} }
Device device = deviceService.findDeviceByTenantIdAndName(deviceProfile.getTenantId(), deviceName); Device device = deviceService.findDeviceByTenantIdAndName(deviceProfile.getTenantId(), deviceName);
String updateDeviceCertificateValue = chain.get(0);
String updateDeviceCertificateHash = EncryptionUtil.getSha3Hash(updateDeviceCertificateValue);
if (device != null) { if (device != null) {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId()); DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());
if (deviceCredentials != null && deviceCredentials.getCredentialsType() == credentialsType) { if (deviceCredentials != null && deviceCredentials.getCredentialsType() == DeviceCredentialsType.X509_CERTIFICATE) {
deviceCredentials = updateDeviceCredentials(device.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType); deviceCredentials = updateDeviceCredentials(device.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, DeviceCredentialsType.X509_CERTIFICATE);
} else if (deviceCredentials == null) { } else if (deviceCredentials == null) {
deviceCredentials = createDeviceCredentials(device.getTenantId(), device.getId(), updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType); deviceCredentials = createDeviceCredentials(device.getTenantId(), device.getId(), updateDeviceCertificateValue, updateDeviceCertificateHash, DeviceCredentialsType.X509_CERTIFICATE);
} }
return getDeviceInfo(deviceCredentials); return getDeviceInfo(deviceCredentials);
} else if (deviceProfile.getProvisionType() == DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN && x509Configuration.isAllowCreateNewDevicesByX509Certificate()) { } else if (deviceProfile.getProvisionType() == DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN && x509Configuration.isAllowCreateNewDevicesByX509Certificate()) {
Device savedDevice = createDevice(deviceProfile.getTenantId(), deviceProfile.getId(), deviceName, deviceProfile.getName()); Device savedDevice = createDevice(deviceProfile.getTenantId(), deviceProfile.getId(), deviceName, deviceProfile.getName());
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getTenantId(), savedDevice.getId()); DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getTenantId(), savedDevice.getId());
deviceCredentials = updateDeviceCredentials(savedDevice.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType); deviceCredentials = updateDeviceCredentials(savedDevice.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, DeviceCredentialsType.X509_CERTIFICATE);
return getDeviceInfo(deviceCredentials); return getDeviceInfo(deviceCredentials);
} else {
log.info("Device doesn't exist and cannot be created due incorrect configuration for X509CertificateChainProvisionConfiguration");
} }
} }
} }
@ -728,12 +726,16 @@ public class DefaultTransportApiService implements TransportApiService {
return l != null ? l : 0; return l != null ? l : 0;
} }
private String extractDeviceNameFromCNByRegEx(String commonName, String regex) { private String extractDeviceNameFromCertificateCNByRegEx(String x509Value, String regex) {
Pattern pattern = Pattern.compile(regex); try {
Matcher matcher = pattern.matcher(commonName); String commonName = SslUtil.parseCommonName(readCertFile(x509Value));
if (matcher.find()) { log.trace("Extract CN [{}] by regex pattern [{}]", commonName, regex);
return matcher.group(0); Pattern pattern = Pattern.compile(regex);
} Matcher matcher = pattern.matcher(commonName);
if (matcher.find()) {
return matcher.group(0);
}
} catch (Exception ignored) {}
return null; return null;
} }
@ -748,23 +750,26 @@ public class DefaultTransportApiService implements TransportApiService {
return chain; return chain;
} }
private X509Certificate readCertFile(String fileContent) throws Exception { private X509Certificate readCertFile(String fileContent) {
X509Certificate certificate = null; X509Certificate certificate = null;
if (fileContent != null && !fileContent.trim().isEmpty()) { try {
fileContent = fileContent.replace("-----BEGIN CERTIFICATE-----", "") if (fileContent != null && !fileContent.trim().isEmpty()) {
.replace("-----END CERTIFICATE-----", "") fileContent = fileContent.replace("-----BEGIN CERTIFICATE-----", "")
.replaceAll("\\s", ""); .replace("-----END CERTIFICATE-----", "")
byte[] decoded = Base64.decodeBase64(fileContent); .replaceAll("\\s", "");
CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); byte[] decoded = Base64.decodeBase64(fileContent);
try (InputStream inStream = new ByteArrayInputStream(decoded)) { CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
certificate = (X509Certificate) certFactory.generateCertificate(inStream); try (InputStream inStream = new ByteArrayInputStream(decoded)) {
certificate = (X509Certificate) certFactory.generateCertificate(inStream);
}
} }
} } catch (Exception ignored) {}
return certificate; return certificate;
} }
private DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials, String certificateValue, private DeviceCredentials updateDeviceCredentials(TenantId tenantId, DeviceCredentials deviceCredentials, String certificateValue,
String certificateHash, DeviceCredentialsType credentialsType) { String certificateHash, DeviceCredentialsType credentialsType) {
log.trace("Updating device credentials [{}] with certificate id [{}]", deviceCredentials, certificateHash);
deviceCredentials.setCredentialsId(certificateHash); deviceCredentials.setCredentialsId(certificateHash);
deviceCredentials.setCredentialsValue(certificateValue); deviceCredentials.setCredentialsValue(certificateValue);
deviceCredentials.setCredentialsType(credentialsType); deviceCredentials.setCredentialsType(credentialsType);
@ -773,6 +778,7 @@ public class DefaultTransportApiService implements TransportApiService {
private DeviceCredentials createDeviceCredentials(TenantId tenantId, DeviceId deviceId, String certificateValue, private DeviceCredentials createDeviceCredentials(TenantId tenantId, DeviceId deviceId, String certificateValue,
String certificateHash, DeviceCredentialsType credentialsType) { String certificateHash, DeviceCredentialsType credentialsType) {
log.trace("Creating new deviceCredentials for device [{}] with certificate id [{}]", deviceId, certificateHash);
DeviceCredentials createDevCredentials = new DeviceCredentials(); DeviceCredentials createDevCredentials = new DeviceCredentials();
createDevCredentials.setDeviceId(deviceId); createDevCredentials.setDeviceId(deviceId);
createDevCredentials.setCredentialsType(credentialsType); createDevCredentials.setCredentialsType(credentialsType);
@ -782,11 +788,14 @@ public class DefaultTransportApiService implements TransportApiService {
} }
private Device createDevice(TenantId tenantId, DeviceProfileId deviceProfileId, String deviceName, String type) { private Device createDevice(TenantId tenantId, DeviceProfileId deviceProfileId, String deviceName, String type) {
log.trace("Creating new device for deviceProfile [{}] with device name [{}]", deviceProfileId, deviceName);
Device device = new Device(); Device device = new Device();
device.setTenantId(tenantId); device.setTenantId(tenantId);
device.setDeviceProfileId(deviceProfileId); device.setDeviceProfileId(deviceProfileId);
device.setName(deviceName); device.setName(deviceName);
device.setType(type); device.setType(type);
return deviceService.saveDevice(device); device = deviceService.saveDevice(device);
tbClusterService.onDeviceUpdated(device, null);
return device;
} }
} }

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

@ -735,7 +735,7 @@ transport:
# MQTT SSL configuration # MQTT SSL configuration
ssl: ssl:
# Enable/disable SSL support # Enable/disable SSL support
enabled: "${MQTT_SSL_ENABLED:false}" enabled: "${MQTT_SSL_ENABLED:true}"
# MQTT SSL bind address # MQTT SSL bind address
bind_address: "${MQTT_SSL_BIND_ADDRESS:0.0.0.0}" bind_address: "${MQTT_SSL_BIND_ADDRESS:0.0.0.0}"
# MQTT SSL bind port # MQTT SSL bind port
@ -749,11 +749,11 @@ transport:
# PEM server credentials # PEM server credentials
pem: pem:
# Path to the server certificate file (holds server certificate or certificate chain, may include server private key) # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)
cert_file: "${MQTT_SSL_PEM_CERT:mqttserver.pem}" cert_file: "${MQTT_SSL_PEM_CERT:/home/developer/server.pem}"
# Path to the server certificate private key file. Optional by default. Required if the private key is not present in server certificate file; # Path to the server certificate private key file. Optional by default. Required if the private key is not present in server certificate file;
key_file: "${MQTT_SSL_PEM_KEY:mqttserver_key.pem}" key_file: "${MQTT_SSL_PEM_KEY:/home/developer/server_key.pem}"
# Server certificate private key password (optional) # Server certificate private key password (optional)
key_password: "${MQTT_SSL_PEM_KEY_PASSWORD:server_key_password}" key_password: "${MQTT_SSL_PEM_KEY_PASSWORD:}"
# Keystore server credentials # Keystore server credentials
keystore: keystore:
# Type of the key store (JKS or PKCS12) # Type of the key store (JKS or PKCS12)

17
application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java

@ -96,33 +96,34 @@ public class DefaultTransportApiServiceTest {
private final String deviceCertificate = "-----BEGIN CERTIFICATE-----Device certificate value-----END CERTIFICATE-----"; private final String deviceCertificate = "-----BEGIN CERTIFICATE-----Device certificate value-----END CERTIFICATE-----";
private final String deviceProfileCertificate = "-----BEGIN CERTIFICATE-----Device profile certificate value-----END CERTIFICATE-----"; private final String deviceProfileCertificate = "-----BEGIN CERTIFICATE-----Device profile certificate value-----END CERTIFICATE-----";
private final String[] chain = new String[]{deviceCertificate, deviceProfileCertificate};
@Test @Test
public void validateExistingDeviceX509Certificate() { public void validateExistingDeviceX509Certificate() {
var device = createDevice(); var device = createDevice();
when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device)); when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device));
var deviceCredentials = createDeviceCredentials(deviceCertificate, device.getId()); var deviceCredentials = createDeviceCredentials(chain[0], device.getId());
when(deviceCredentialsService.findDeviceCredentialsByCredentialsId(any())).thenReturn(deviceCredentials); when(deviceCredentialsService.findDeviceCredentialsByCredentialsId(any())).thenReturn(deviceCredentials);
service.validateOrCreateDeviceX509Certificate(deviceCertificate, DeviceCredentialsType.X509_CERTIFICATE); service.validateOrCreateDeviceX509Certificate(chain[0]);
verify(deviceCredentialsService, times(1)).findDeviceCredentialsByCredentialsId(any()); verify(deviceCredentialsService, times(1)).findDeviceCredentialsByCredentialsId(any());
} }
@Test @Test
public void updateExistingDeviceX509Certificate() { public void updateExistingDeviceX509Certificate() {
var deviceProfile = createDeviceProfile(deviceProfileCertificate); var deviceProfile = createDeviceProfile(chain[1]);
when(deviceProfileService.findDeviceProfileByCertificateHash(any())).thenReturn(deviceProfile); when(deviceProfileService.findDeviceProfileByCertificateHash(any())).thenReturn(deviceProfile);
var device = createDevice(); var device = createDevice();
when(deviceService.findDeviceByTenantIdAndName(any(), any())).thenReturn(device); when(deviceService.findDeviceByTenantIdAndName(any(), any())).thenReturn(device);
when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device)); when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device));
var deviceCredentials = createDeviceCredentials(deviceCertificate, device.getId()); var deviceCredentials = createDeviceCredentials(chain[0], device.getId());
when(deviceCredentialsService.findDeviceCredentialsByDeviceId(any(), any())).thenReturn(deviceCredentials); when(deviceCredentialsService.findDeviceCredentialsByDeviceId(any(), any())).thenReturn(deviceCredentials);
when(deviceCredentialsService.updateDeviceCredentials(any(), any())).thenReturn(deviceCredentials); when(deviceCredentialsService.updateDeviceCredentials(any(), any())).thenReturn(deviceCredentials);
service.validateOrCreateDeviceX509Certificate(deviceProfileCertificate, DeviceCredentialsType.X509_CERTIFICATE); service.validateOrCreateDeviceX509Certificate(chain[1]);
verify(deviceProfileService, times(1)).findDeviceProfileByCertificateHash(any()); verify(deviceProfileService, times(1)).findDeviceProfileByCertificateHash(any());
verify(deviceService, times(1)).findDeviceByTenantIdAndName(any(), any()); verify(deviceService, times(1)).findDeviceByTenantIdAndName(any(), any());
verify(deviceCredentialsService, times(1)).findDeviceCredentialsByDeviceId(any(), any()); verify(deviceCredentialsService, times(1)).findDeviceCredentialsByDeviceId(any(), any());
@ -131,18 +132,18 @@ public class DefaultTransportApiServiceTest {
@Test @Test
public void createDeviceByX509Provision() { public void createDeviceByX509Provision() {
var deviceProfile = createDeviceProfile(deviceProfileCertificate); var deviceProfile = createDeviceProfile(chain[1]);
when(deviceProfileService.findDeviceProfileByCertificateHash(any())).thenReturn(deviceProfile); when(deviceProfileService.findDeviceProfileByCertificateHash(any())).thenReturn(deviceProfile);
var device = createDevice(); var device = createDevice();
when(deviceService.saveDevice(any())).thenReturn(device); when(deviceService.saveDevice(any())).thenReturn(device);
when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device)); when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device));
var deviceCredentials = createDeviceCredentials(deviceCertificate, device.getId()); var deviceCredentials = createDeviceCredentials(chain[0], device.getId());
when(deviceCredentialsService.findDeviceCredentialsByDeviceId(any(), any())).thenReturn(deviceCredentials); when(deviceCredentialsService.findDeviceCredentialsByDeviceId(any(), any())).thenReturn(deviceCredentials);
when(deviceCredentialsService.updateDeviceCredentials(any(), any())).thenReturn(deviceCredentials); when(deviceCredentialsService.updateDeviceCredentials(any(), any())).thenReturn(deviceCredentials);
service.validateOrCreateDeviceX509Certificate(deviceProfileCertificate, DeviceCredentialsType.X509_CERTIFICATE); service.validateOrCreateDeviceX509Certificate(chain[1]);
verify(deviceProfileService, times(1)).findDeviceProfileByCertificateHash(any()); verify(deviceProfileService, times(1)).findDeviceProfileByCertificateHash(any());
verify(deviceService, times(1)).findDeviceByTenantIdAndName(any(), any()); verify(deviceService, times(1)).findDeviceByTenantIdAndName(any(), any());
verify(deviceCredentialsService, times(1)).findDeviceCredentialsByDeviceId(any(), any()); verify(deviceCredentialsService, times(1)).findDeviceCredentialsByDeviceId(any(), any());

7
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/X509CertificateChainProvisionConfiguration.java

@ -24,11 +24,16 @@ import org.thingsboard.server.common.data.DeviceProfileProvisionType;
@NoArgsConstructor @NoArgsConstructor
public class X509CertificateChainProvisionConfiguration implements DeviceProfileProvisionConfiguration { public class X509CertificateChainProvisionConfiguration implements DeviceProfileProvisionConfiguration {
private String provisionDeviceSecret;
private String certificateValue; private String certificateValue;
private String certificateRegExPattern; private String certificateRegExPattern;
private boolean allowCreateNewDevicesByX509Certificate; private boolean allowCreateNewDevicesByX509Certificate;
@Override
public String getProvisionDeviceSecret() {
// ignore device secret for this strategy
return null;
}
@Override @Override
public DeviceProfileProvisionType getType() { public DeviceProfileProvisionType getType() {
return DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN; return DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN;

10
common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java

@ -164,8 +164,14 @@ public class MqttSslHandlerProvider {
} }
}); });
latch.await(10, TimeUnit.SECONDS); latch.await(10, TimeUnit.SECONDS);
if (!clientDeviceCertValue.equals(credentialsBodyHolder[0])) { if (chain.length == 1) {
throw new CertificateException("Invalid Certificate's chain. Cannot find such device credentials."); if (!clientDeviceCertValue.equals(credentialsBodyHolder[0])) {
throw new CertificateException("Invalid Device Certificate");
}
} else {
if (!clientDeviceCertValue.equals(credentialsBodyHolder[0])) {
throw new CertificateException("Invalid Chain of X509 Certificates");
}
} }
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);

1
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java

@ -58,6 +58,7 @@ public class SslUtil {
try { try {
x500name = new JcaX509CertificateHolder(certificate).getSubject(); x500name = new JcaX509CertificateHolder(certificate).getSubject();
} catch (CertificateEncodingException e) { } catch (CertificateEncodingException e) {
log.warn("Cannot parse CN from device certificate");
throw new RuntimeException(e); throw new RuntimeException(e);
} }
RDN cn = x500name.getRDNs(BCStyle.CN)[0]; RDN cn = x500name.getRDNs(BCStyle.CN)[0];

22
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -135,12 +135,11 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
@Override @Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) { public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) {
log.trace("Executing saveDeviceProfile [{}]", deviceProfile); log.trace("Executing saveDeviceProfile [{}]", deviceProfile);
X509CertificateChainProvisionConfiguration x509Configuration = new X509CertificateChainProvisionConfiguration();
if (deviceProfile.getProfileData() != null && deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) { if (deviceProfile.getProfileData() != null && deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) {
x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration(); X509CertificateChainProvisionConfiguration x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration();
} if (x509Configuration.getCertificateValue() != null) {
if (x509Configuration.getCertificateValue() != null) { formatDeviceProfileCertificate(deviceProfile, x509Configuration);
formatDeviceProfileCertificate(deviceProfile, x509Configuration); }
} }
DeviceProfile oldDeviceProfile = deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId); DeviceProfile oldDeviceProfile = deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId);
DeviceProfile savedDeviceProfile; DeviceProfile savedDeviceProfile;
@ -351,24 +350,25 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
} }
private void formatDeviceProfileCertificate(DeviceProfile deviceProfile, X509CertificateChainProvisionConfiguration x509Configuration) { private void formatDeviceProfileCertificate(DeviceProfile deviceProfile, X509CertificateChainProvisionConfiguration x509Configuration) {
String certificateValue = formatCertificateValue(x509Configuration.getCertificateValue()); String formattedCertificateValue = formatCertificateValue(x509Configuration.getCertificateValue());
String cert = regexCertificateChain(certificateValue); String cert = fetchLeafCertificateFromChain(formattedCertificateValue);
String sha3Hash = EncryptionUtil.getSha3Hash(cert); String sha3Hash = EncryptionUtil.getSha3Hash(cert);
DeviceProfileData deviceProfileData = deviceProfile.getProfileData(); DeviceProfileData deviceProfileData = deviceProfile.getProfileData();
x509Configuration.setCertificateValue(certificateValue); x509Configuration.setCertificateValue(formattedCertificateValue);
deviceProfileData.setProvisionConfiguration(x509Configuration); deviceProfileData.setProvisionConfiguration(x509Configuration);
deviceProfile.setProfileData(deviceProfileData); deviceProfile.setProfileData(deviceProfileData);
deviceProfile.setCertificateHash(sha3Hash); deviceProfile.setCertificateHash(sha3Hash);
} }
private String regexCertificateChain(String chain) { private String fetchLeafCertificateFromChain(String value) {
String regex = "-----BEGIN CERTIFICATE-----\\s*.*?\\s*-----END CERTIFICATE-----"; String regex = "-----BEGIN CERTIFICATE-----\\s*.*?\\s*-----END CERTIFICATE-----";
Pattern pattern = Pattern.compile(regex); Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(chain); Matcher matcher = pattern.matcher(value);
if (matcher.find()) { if (matcher.find()) {
// if the method receives a chain it fetches the leaf (end-entity) certificate, else if it gets a single certificate, it returns the single certificate
return matcher.group(0); return matcher.group(0);
} }
return chain; return value;
} }
private String formatCertificateValue(String certificateValue) { private String formatCertificateValue(String certificateValue) {

Loading…
Cancel
Save