Browse Source

Add unit tests and update regex pattern to convert chain to list

pull/7935/head
Andrii Landiak 4 years ago
parent
commit
e9586daf9d
  1. 85
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  2. 19
      application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java
  3. 174
      application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java
  4. 7
      application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java
  5. 5
      application/src/test/java/org/thingsboard/server/transport/mqtt/MqttTestConfigProperties.java
  6. 1
      common/cluster-api/src/main/proto/queue.proto
  7. 6
      common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java
  8. 3
      common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java
  9. 3
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java
  10. 27
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

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

@ -107,11 +107,9 @@ import org.thingsboard.server.service.resource.TbResourceService;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@ -243,41 +241,44 @@ public class DefaultTransportApiService implements TransportApiService {
}
}
private ListenableFuture<TransportApiResponseMsg> validateOrCreateDeviceX509Certificate(String certChain, DeviceCredentialsType credentialsType) {
protected ListenableFuture<TransportApiResponseMsg> validateOrCreateDeviceX509Certificate(String certChain, DeviceCredentialsType credentialsType) {
List<String> chain = convertX509CertificateChainToList(certChain);
String updateDeviceCertificateValue = chain.get(0);
String updateDeviceCertificateHash = EncryptionUtil.getSha3Hash(updateDeviceCertificateValue);
String deviceCommonName = "";
try {
List<X509Certificate> chain = getX509CertificateChainFromString(certChain);
String updateDeviceCertificateValue = SslUtil.getCertificateString(chain.get(0));
String updateDeviceCertificateHash = EncryptionUtil.getSha3Hash(updateDeviceCertificateValue);
for (X509Certificate cert: chain) {
String certificateValue = SslUtil.getCertificateString(cert);
String certificateHash = EncryptionUtil.getSha3Hash(certificateValue);
DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(certificateHash);
if (credentials != null && credentials.getCredentialsType() == credentialsType) {
return getDeviceInfo(credentials);
deviceCommonName = SslUtil.parseCommonName(readCertFile(chain.get(0)));
} catch (Exception ignored) {
}
for (String certificateValue : chain) {
String certificateHash = EncryptionUtil.getSha3Hash(certificateValue);
DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(certificateHash);
if (credentials != null && credentials.getCredentialsType() == credentialsType) {
return getDeviceInfo(credentials);
}
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileByCertificateHash(certificateHash);
if (deviceProfile != null) {
String deviceName = extractDeviceNameFromCNByRegEx(deviceCommonName, deviceProfile.getCertificateRegexPattern());
if (deviceName == null) {
log.error("Device name cannot be unmatched from CN!");
return getEmptyTransportApiResponseFuture();
}
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileByCertificateHash(certificateHash);
if (deviceProfile != null) {
String deviceName = extractDeviceNameFromCNByRegEx(SslUtil.parseCommonName(chain.get(0)), deviceProfile.getCertificateRegexPattern());
Device device = deviceService.findDeviceByTenantIdAndName(deviceProfile.getTenantId(), deviceName);
if (device != null) {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());
if (deviceCredentials != null && deviceCredentials.getCredentialsType() == credentialsType) {
deviceCredentials = updateDeviceCredentials(device.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType);
} else if (deviceCredentials == null) {
deviceCredentials = createDeviceCredentials(device.getTenantId(), device.getId(), updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType);
}
return getDeviceInfo(deviceCredentials);
} else if (deviceProfile.getProvisionType() == DeviceProfileProvisionType.ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE && deviceProfile.isAllowCreateNewDevicesByX509Strategy()) {
Device savedDevice = createDevice(deviceProfile.getTenantId(), deviceProfile.getId(), deviceName, deviceProfile.getName());
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getTenantId(), savedDevice.getId());
deviceCredentials = updateDeviceCredentials(savedDevice.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType);
return getDeviceInfo(deviceCredentials);
Device device = deviceService.findDeviceByTenantIdAndName(deviceProfile.getTenantId(), deviceName);
if (device != null) {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());
if (deviceCredentials != null && deviceCredentials.getCredentialsType() == credentialsType) {
deviceCredentials = updateDeviceCredentials(device.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType);
} else if (deviceCredentials == null) {
deviceCredentials = createDeviceCredentials(device.getTenantId(), device.getId(), updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType);
}
return getDeviceInfo(deviceCredentials);
} else if (deviceProfile.getProvisionType() == DeviceProfileProvisionType.ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE && deviceProfile.isAllowCreateNewDevicesByX509Strategy()) {
Device savedDevice = createDevice(deviceProfile.getTenantId(), deviceProfile.getId(), deviceName, deviceProfile.getName());
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(savedDevice.getTenantId(), savedDevice.getId());
deviceCredentials = updateDeviceCredentials(savedDevice.getTenantId(), deviceCredentials, updateDeviceCertificateValue, updateDeviceCertificateHash, credentialsType);
return getDeviceInfo(deviceCredentials);
}
}
} catch (CertificateEncodingException e) {
throw new RuntimeException(e);
}
return getEmptyTransportApiResponseFuture();
}
@ -727,19 +728,17 @@ public class DefaultTransportApiService implements TransportApiService {
if (matcher.find()) {
return matcher.group(0);
}
return commonName;
return null;
}
private List<X509Certificate> getX509CertificateChainFromString(String certificateChain) {
List<X509Certificate> chain = new ArrayList<>();
String[] test = Arrays.stream(certificateChain.split("-----BEGIN CERTIFICATE-----")).filter(e -> e.trim().length() > 0).map(EncryptionUtil::certTrimNewLines).toArray(String[]::new);
Arrays.stream(test).forEach(s -> {
try {
chain.add(readCertFile(s));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
private List<String> convertX509CertificateChainToList(String certificateChain) {
List<String> chain = new ArrayList<>();
String regex = "-----BEGIN CERTIFICATE-----\\s*.*?\\s*-----END CERTIFICATE-----";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(certificateChain);
while (matcher.find()) {
chain.add(EncryptionUtil.certTrimNewLines(matcher.group()));
}
return chain;
}

19
application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java

@ -298,6 +298,25 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController
tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
}
@Test
public void testSaveDeviceProfileWithSameCertificateHash() throws Exception {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
deviceProfile.setCertificateHash("Certificate Hash");
doPost("/api/deviceProfile", deviceProfile).andExpect(status().isOk());
DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile 2");
deviceProfile2.setCertificateHash("Certificate Hash");
Mockito.reset(tbClusterService, auditLogService);
String msgError = "Device profile with such certificate hash already exists";
doPost("/api/deviceProfile", deviceProfile2)
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString(msgError)));
testNotifyEntityEqualsOneTimeServiceNeverError(deviceProfile, savedTenant.getId(),
tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
}
@Test
public void testChangeDeviceProfileTypeNull() throws Exception {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");

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

@ -0,0 +1,174 @@
/**
* 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.service.transport;
import com.google.common.util.concurrent.Futures;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
import org.thingsboard.server.common.msg.EncryptionUtil;
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.DeviceService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.queue.QueueService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.resource.TbResourceService;
import java.util.UUID;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@Slf4j
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = DefaultTransportApiService.class)
public class DefaultTransportApiServiceTest {
@MockBean
protected TbDeviceProfileCache deviceProfileCache;
@MockBean
protected TbTenantProfileCache tenantProfileCache;
@MockBean
protected TbApiUsageStateService apiUsageStateService;
@MockBean
protected DeviceService deviceService;
@MockBean
protected DeviceProfileService deviceProfileService;
@MockBean
protected RelationService relationService;
@MockBean
protected DeviceCredentialsService deviceCredentialsService;
@MockBean
protected DbCallbackExecutorService dbCallbackExecutorService;
@MockBean
protected TbClusterService tbClusterService;
@MockBean
protected DataDecodingEncodingService dataDecodingEncodingService;
@MockBean
protected DeviceProvisionService deviceProvisionService;
@MockBean
protected TbResourceService resourceService;
@MockBean
protected OtaPackageService otaPackageService;
@MockBean
protected OtaPackageDataCache otaPackageDataCache;
@MockBean
protected QueueService queueService;
@SpyBean
DefaultTransportApiService service;
private final String deviceCertificate = "-----BEGIN CERTIFICATE-----Device certificate value-----END CERTIFICATE-----";
private final String deviceProfileCertificate = "-----BEGIN CERTIFICATE-----Device profile certificate value-----END CERTIFICATE-----";
@Test
public void validateExistingDeviceX509Certificate() {
var device = createDevice();
when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device));
var deviceCredentials = createDeviceCredentials(deviceCertificate, device.getId());
when(deviceCredentialsService.findDeviceCredentialsByCredentialsId(any())).thenReturn(deviceCredentials);
service.validateOrCreateDeviceX509Certificate(deviceCertificate, DeviceCredentialsType.X509_CERTIFICATE);
verify(deviceCredentialsService, times(1)).findDeviceCredentialsByCredentialsId(any());
}
@Test
public void updateExistingDeviceX509Certificate() {
var deviceProfile = createDeviceProfile(deviceProfileCertificate);
when(deviceProfileService.findDeviceProfileByCertificateHash(any())).thenReturn(deviceProfile);
var device = createDevice();
when(deviceService.findDeviceByTenantIdAndName(any(), any())).thenReturn(device);
when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device));
var deviceCredentials = createDeviceCredentials(deviceCertificate, device.getId());
when(deviceCredentialsService.findDeviceCredentialsByDeviceId(any(), any())).thenReturn(deviceCredentials);
when(deviceCredentialsService.updateDeviceCredentials(any(), any())).thenReturn(deviceCredentials);
service.validateOrCreateDeviceX509Certificate(deviceProfileCertificate, DeviceCredentialsType.X509_CERTIFICATE);
verify(deviceProfileService, times(1)).findDeviceProfileByCertificateHash(any());
verify(deviceService, times(1)).findDeviceByTenantIdAndName(any(), any());
verify(deviceCredentialsService, times(1)).findDeviceCredentialsByDeviceId(any(), any());
verify(deviceCredentialsService, times(1)).updateDeviceCredentials(any(), any());
}
@Test
public void createDeviceByX509Provision() {
var deviceProfile = createDeviceProfile(deviceProfileCertificate);
when(deviceProfileService.findDeviceProfileByCertificateHash(any())).thenReturn(deviceProfile);
var device = createDevice();
when(deviceService.saveDevice(any())).thenReturn(device);
when(deviceService.findDeviceByIdAsync(any(), any())).thenReturn(Futures.immediateFuture(device));
var deviceCredentials = createDeviceCredentials(deviceCertificate, device.getId());
when(deviceCredentialsService.findDeviceCredentialsByDeviceId(any(), any())).thenReturn(deviceCredentials);
when(deviceCredentialsService.updateDeviceCredentials(any(), any())).thenReturn(deviceCredentials);
service.validateOrCreateDeviceX509Certificate(deviceProfileCertificate, DeviceCredentialsType.X509_CERTIFICATE);
verify(deviceProfileService, times(1)).findDeviceProfileByCertificateHash(any());
verify(deviceService, times(1)).findDeviceByTenantIdAndName(any(), any());
verify(deviceCredentialsService, times(1)).findDeviceCredentialsByDeviceId(any(), any());
verify(deviceCredentialsService, times(1)).updateDeviceCredentials(any(), any());
}
private DeviceCredentials createDeviceCredentials(String certificateValue, DeviceId deviceId) {
DeviceCredentials deviceCredentials = new DeviceCredentials();
deviceCredentials.setDeviceId(deviceId);
deviceCredentials.setCredentialsValue(certificateValue);
deviceCredentials.setCredentialsId(EncryptionUtil.getSha3Hash(certificateValue));
deviceCredentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE);
return deviceCredentials;
}
private DeviceProfile createDeviceProfile(String certificateValue) {
DeviceProfile deviceProfile = new DeviceProfile();
deviceProfile.setCertificateValue(certificateValue);
deviceProfile.setCertificateHash(EncryptionUtil.getSha3Hash(certificateValue));
deviceProfile.setCertificateRegexPattern("^$");
deviceProfile.setAllowCreateNewDevicesByX509Strategy(true);
deviceProfile.setProvisionType(DeviceProfileProvisionType.ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE);
return deviceProfile;
}
private Device createDevice() {
Device device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
return device;
}
}

7
application/src/test/java/org/thingsboard/server/transport/mqtt/AbstractMqttIntegrationTest.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration;
import org.thingsboard.server.common.data.device.profile.AllowCreatingNewDevicesByX509CertificateProvisionConfiguration;
import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration;
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
@ -94,6 +95,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
deviceProfile.setProvisionType(provisionType);
deviceProfile.setProvisionDeviceKey(config.getProvisionKey());
deviceProfile.setDescription(transportPayloadType.name() + " Test");
deviceProfile.setAllowCreateNewDevicesByX509Strategy(config.allowCreatingNewDeviceByX509Strategy);
deviceProfile.setCertificateValue("Device Profile certificate value");
deviceProfile.setCertificateRegexPattern(config.getRegEx());
DeviceProfileData deviceProfileData = new DeviceProfileData();
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();
MqttDeviceProfileTransportConfiguration mqttDeviceProfileTransportConfiguration = new MqttDeviceProfileTransportConfiguration();
@ -144,6 +148,9 @@ public abstract class AbstractMqttIntegrationTest extends AbstractTransportInteg
case CHECK_PRE_PROVISIONED_DEVICES:
provisionConfiguration = new CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration(config.getProvisionSecret());
break;
case ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE:
provisionConfiguration = new AllowCreatingNewDevicesByX509CertificateProvisionConfiguration(config.getProvisionSecret());
break;
case DISABLED:
default:
provisionConfiguration = new DisabledDeviceProfileProvisionConfiguration(config.getProvisionSecret());

5
application/src/test/java/org/thingsboard/server/transport/mqtt/MqttTestConfigProperties.java

@ -40,9 +40,14 @@ public class MqttTestConfigProperties {
boolean enableCompatibilityWithJsonPayloadFormat;
boolean useJsonPayloadFormatForDefaultDownlinkTopics;
boolean sendAckOnValidationException;
boolean allowCreatingNewDeviceByX509Strategy;
DeviceProfileProvisionType provisionType;
String provisionKey;
String provisionSecret;
String x509DeviceCertificate;
String x509DeviceProfileCertificate;
String commonName;
String regEx;
}

1
common/cluster-api/src/main/proto/queue.proto

@ -422,7 +422,6 @@ message CredentialsDataProto {
ValidateDeviceTokenRequestMsg validateDeviceTokenRequestMsg = 1;
ValidateDeviceX509CertRequestMsg validateDeviceX509CertRequestMsg = 2;
ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 3;
ValidateOrCreateDeviceX509CertRequestMsg validateOrCreateDeviceX509CertRequestMsg = 4;
}
message ProvisionDeviceRequestMsg {

6
common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java

@ -35,9 +35,11 @@ public class EncryptionUtil {
.replaceAll("-----END CERTIFICATE-----", "");
}
public static String certTrimNewLinesWithoutBeginEnd(String input) {
public static String certTrimNewLinesForChainInDeviceProfile(String input) {
return input.replaceAll("\n", "")
.replaceAll("\r", "");
.replaceAll("\r", "")
.replaceAll("-----BEGIN CERTIFICATE-----", "-----BEGIN CERTIFICATE-----\n")
.replaceAll("-----END CERTIFICATE-----", "\n-----END CERTIFICATE-----\n");
}
public static String pubkTrimNewLines(String input) {

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

@ -41,7 +41,6 @@ import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.CountDownLatch;
@ -168,7 +167,7 @@ public class MqttSslHandlerProvider {
if (!clientDeviceCertValue.equals(credentialsBodyHolder[0])) {
throw new CertificateException("Invalid Certificate's chain. Cannot find such device credentials.");
}
} catch (CertificateEncodingException | InterruptedException e) {
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}

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

@ -27,7 +27,6 @@ import org.thingsboard.server.common.msg.EncryptionUtil;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
/**
* @author Valerii Sosliuk
@ -49,7 +48,7 @@ public class SslUtil {
String end = "-----END CERTIFICATE-----";
StringBuilder stringBuilder = new StringBuilder();
for (Certificate cert: chain) {
stringBuilder.append(begin).append(EncryptionUtil.certTrimNewLinesWithoutBeginEnd(Base64Utils.encodeToString(cert.getEncoded()))).append(end).append("\n");
stringBuilder.append(begin).append(EncryptionUtil.certTrimNewLines(Base64Utils.encodeToString(cert.getEncoded()))).append(end).append("\n");
}
return stringBuilder.toString();
}

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

@ -48,6 +48,10 @@ import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator;
import java.io.ByteArrayInputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -342,17 +346,15 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
}
private void formatDeviceProfileCertificate(DeviceProfile deviceProfile) {
String certificateValue = deviceProfile.getCertificateValue();
String certificateValue = formatCertificateValue(deviceProfile.getCertificateValue());
String cert = regexCertificateChain(certificateValue);
String sha3Hash = EncryptionUtil.getSha3Hash(cert);
deviceProfile.setCertificateValue(certificateValue);
deviceProfile.setCertificateHash(sha3Hash);
if (!isCertificateChain(certificateValue)) {
deviceProfile.setCertificateValue(EncryptionUtil.certTrimNewLines(certificateValue));
}
}
private String regexCertificateChain(String chain) {
String regex = "-----BEGIN CERTIFICATE-----\\s*((.+\\s+)*?)-----END CERTIFICATE-----";
String regex = "-----BEGIN CERTIFICATE-----\\s*.*?\\s*-----END CERTIFICATE-----";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(chain);
if (matcher.find()) {
@ -361,9 +363,18 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
return chain;
}
private boolean isCertificateChain(String certificateValue) {
int count = certificateValue.split("-----BEGIN CERTIFICATE", -1).length - 1;
return count > 1;
private String formatCertificateValue(String certificateValue) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream inputStream = new ByteArrayInputStream(certificateValue.getBytes());
Certificate[] certificates = cf.generateCertificates(inputStream).toArray(new Certificate[0]);
if (certificates.length > 1) {
return EncryptionUtil.certTrimNewLinesForChainInDeviceProfile(certificateValue);
}
return EncryptionUtil.certTrimNewLines(certificateValue);
} catch (CertificateException e) {
throw new RuntimeException(e);
}
}
}

Loading…
Cancel
Save