Fix schema and micro refactoring

This commit is contained in:
Andrii Landiak 2023-02-01 16:49:00 +02:00
parent e9586daf9d
commit 0943b80d8e
14 changed files with 47 additions and 65 deletions

View File

@ -31,9 +31,6 @@ CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id)
ALTER TABLE device_profile
ADD COLUMN IF NOT EXISTS certificate_hash varchar,
ADD COLUMN IF NOT EXISTS certificate_value varchar,
ADD COLUMN IF NOT EXISTS certificate_regex_pattern varchar(255),
ADD COLUMN IF NOT EXISTS allow_create_device_by_x509 boolean,
DROP CONSTRAINT IF EXISTS device_profile_credentials_hash_unq_key,
ADD CONSTRAINT device_profile_credentials_hash_unq_key UNIQUE (certificate_hash);

View File

@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.device.data.Lwm2mDeviceTransportConfig
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration;
import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
import org.thingsboard.server.common.data.device.profile.X509CertificateChainProvisionConfiguration;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
@ -173,7 +174,7 @@ public class DefaultTransportApiService implements TransportApiService {
result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);
} else if (transportApiRequestMsg.hasValidateOrCreateX509CertRequestMsg()) {
TransportProtos.ValidateOrCreateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateOrCreateX509CertRequestMsg();
result = validateOrCreateDeviceX509Certificate(msg.getCertificate(), DeviceCredentialsType.X509_CERTIFICATE);
result = validateOrCreateDeviceX509Certificate(msg.getCertificateChain(), DeviceCredentialsType.X509_CERTIFICATE);
} else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {
result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());
} else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {
@ -258,7 +259,11 @@ public class DefaultTransportApiService implements TransportApiService {
}
DeviceProfile deviceProfile = deviceProfileService.findDeviceProfileByCertificateHash(certificateHash);
if (deviceProfile != null) {
String deviceName = extractDeviceNameFromCNByRegEx(deviceCommonName, deviceProfile.getCertificateRegexPattern());
X509CertificateChainProvisionConfiguration x509Configuration = new X509CertificateChainProvisionConfiguration();
if (deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) {
x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration();
}
String deviceName = extractDeviceNameFromCNByRegEx(deviceCommonName, x509Configuration.getCertificateRegExPattern());
if (deviceName == null) {
log.error("Device name cannot be unmatched from CN!");
return getEmptyTransportApiResponseFuture();
@ -272,7 +277,7 @@ public class DefaultTransportApiService implements TransportApiService {
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()) {
} else if (deviceProfile.getProvisionType() == DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN && x509Configuration.isAllowCreateNewDevicesByX509Certificate()) {
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);

View File

@ -29,6 +29,9 @@ 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.device.profile.X509CertificateChainProvisionConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.device.profile.DeviceProfileProvisionConfiguration;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
@ -158,11 +161,15 @@ public class DefaultTransportApiServiceTest {
private DeviceProfile createDeviceProfile(String certificateValue) {
DeviceProfile deviceProfile = new DeviceProfile();
deviceProfile.setCertificateValue(certificateValue);
DeviceProfileData deviceProfileData = new DeviceProfileData();
X509CertificateChainProvisionConfiguration provision = new X509CertificateChainProvisionConfiguration();
provision.setCertificateValue(certificateValue);
provision.setCertificateRegExPattern("^$");
provision.setAllowCreateNewDevicesByX509Certificate(true);
deviceProfileData.setProvisionConfiguration(provision);
deviceProfile.setProfileData(deviceProfileData);
deviceProfile.setCertificateHash(EncryptionUtil.getSha3Hash(certificateValue));
deviceProfile.setCertificateRegexPattern("^$");
deviceProfile.setAllowCreateNewDevicesByX509Strategy(true);
deviceProfile.setProvisionType(DeviceProfileProvisionType.ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE);
deviceProfile.setProvisionType(DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN);
return deviceProfile;
}

View File

@ -27,7 +27,6 @@ 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;
@ -95,9 +94,6 @@ 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();
@ -148,9 +144,6 @@ 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());

View File

@ -40,14 +40,9 @@ 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;
}

View File

@ -170,7 +170,7 @@ message ValidateDeviceX509CertRequestMsg {
}
message ValidateOrCreateDeviceX509CertRequestMsg {
string certificate = 1;
string certificateChain = 1;
}
message ValidateBasicMqttCredRequestMsg {

View File

@ -66,14 +66,8 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H
private DeviceTransportType transportType;
@ApiModelProperty(position = 15, value = "Provisioning strategy.")
private DeviceProfileProvisionType provisionType;
@ApiModelProperty(position = 18, value = "CA certificate value. ")
private String certificateValue;
@ApiModelProperty(position = 19, value = "CA certificate hash. ")
@ApiModelProperty(position = 18, value = "CA certificate hash. ")
private String certificateHash;
@ApiModelProperty(position = 20, value = "Regex to fetch deviceName from CN. ")
private String certificateRegexPattern;
@ApiModelProperty(position = 21, value = "Allow to create new devices by x509 provision strategy. ")
private boolean allowCreateNewDevicesByX509Strategy;
@ApiModelProperty(position = 7, value = "Reference to the rule chain. " +
@ -131,9 +125,6 @@ public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements H
this.firmwareId = deviceProfile.getFirmwareId();
this.softwareId = deviceProfile.getSoftwareId();
this.defaultEdgeRuleChainId = deviceProfile.getDefaultEdgeRuleChainId();
this.allowCreateNewDevicesByX509Strategy = deviceProfile.isAllowCreateNewDevicesByX509Strategy();
this.certificateRegexPattern = deviceProfile.getCertificateRegexPattern();
this.certificateValue = deviceProfile.getCertificateValue();
this.certificateHash = deviceProfile.getCertificateHash();
this.externalId = deviceProfile.getExternalId();
}

View File

@ -19,5 +19,5 @@ public enum DeviceProfileProvisionType {
DISABLED,
ALLOW_CREATE_NEW_DEVICES,
CHECK_PRE_PROVISIONED_DEVICES,
ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE
X509_CERTIFICATE_CHAIN
}

View File

@ -32,7 +32,7 @@ import java.io.Serializable;
@JsonSubTypes.Type(value = DisabledDeviceProfileProvisionConfiguration.class, name = "DISABLED"),
@JsonSubTypes.Type(value = AllowCreateNewDevicesDeviceProfileProvisionConfiguration.class, name = "ALLOW_CREATE_NEW_DEVICES"),
@JsonSubTypes.Type(value = CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration.class, name = "CHECK_PRE_PROVISIONED_DEVICES"),
@JsonSubTypes.Type(value = AllowCreatingNewDevicesByX509CertificateProvisionConfiguration.class, name = "ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE")})
@JsonSubTypes.Type(value = X509CertificateChainProvisionConfiguration.class, name = "X509_CERTIFICATE_CHAIN")})
public interface DeviceProfileProvisionConfiguration extends Serializable {
String getProvisionDeviceSecret();

View File

@ -17,16 +17,21 @@
package org.thingsboard.server.common.data.device.profile;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
@Data
public class AllowCreatingNewDevicesByX509CertificateProvisionConfiguration implements DeviceProfileProvisionConfiguration {
@NoArgsConstructor
public class X509CertificateChainProvisionConfiguration implements DeviceProfileProvisionConfiguration {
private final String provisionDeviceSecret;
private String provisionDeviceSecret;
private String certificateValue;
private String certificateRegExPattern;
private boolean allowCreateNewDevicesByX509Certificate;
@Override
public DeviceProfileProvisionType getType() {
return DeviceProfileProvisionType.ALLOW_CREATING_NEW_DEVICES_BY_X509_CERTIFICATE;
return DeviceProfileProvisionType.X509_CERTIFICATE_CHAIN;
}
}

View File

@ -147,7 +147,7 @@ public class MqttSslHandlerProvider {
try {
String certificateChain = SslUtil.getCertificateChainString(chain);
transportService.process(DeviceTransportType.MQTT, TransportProtos.ValidateOrCreateDeviceX509CertRequestMsg
.newBuilder().setCertificate(certificateChain).build(),
.newBuilder().setCertificateChain(certificateChain).build(),
new TransportServiceCallback<>() {
@Override
public void onSuccess(ValidateDeviceCredentialsResponse msg) {

View File

@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileCon
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.device.profile.DisabledDeviceProfileProvisionConfiguration;
import org.thingsboard.server.common.data.device.profile.X509CertificateChainProvisionConfiguration;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
@ -134,8 +135,12 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
@Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) {
log.trace("Executing saveDeviceProfile [{}]", deviceProfile);
if (deviceProfile.getCertificateValue() != null) {
formatDeviceProfileCertificate(deviceProfile);
X509CertificateChainProvisionConfiguration x509Configuration = new X509CertificateChainProvisionConfiguration();
if (deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) {
x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration();
}
if (x509Configuration.getCertificateValue() != null) {
formatDeviceProfileCertificate(deviceProfile, x509Configuration);
}
DeviceProfile oldDeviceProfile = deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId);
DeviceProfile savedDeviceProfile;
@ -345,11 +350,14 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
profile.getDefaultDashboardId(), profile.getType(), profile.getTransportType());
}
private void formatDeviceProfileCertificate(DeviceProfile deviceProfile) {
String certificateValue = formatCertificateValue(deviceProfile.getCertificateValue());
private void formatDeviceProfileCertificate(DeviceProfile deviceProfile, X509CertificateChainProvisionConfiguration x509Configuration) {
String certificateValue = formatCertificateValue(x509Configuration.getCertificateValue());
String cert = regexCertificateChain(certificateValue);
String sha3Hash = EncryptionUtil.getSha3Hash(cert);
deviceProfile.setCertificateValue(certificateValue);
DeviceProfileData deviceProfileData = deviceProfile.getProfileData();
x509Configuration.setCertificateValue(certificateValue);
deviceProfileData.setProvisionConfiguration(x509Configuration);
deviceProfile.setProfileData(deviceProfileData);
deviceProfile.setCertificateHash(sha3Hash);
}
@ -372,9 +380,8 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
return EncryptionUtil.certTrimNewLinesForChainInDeviceProfile(certificateValue);
}
return EncryptionUtil.certTrimNewLines(certificateValue);
} catch (CertificateException e) {
throw new RuntimeException(e);
}
} catch (CertificateException ignored) {}
return certificateValue;
}
}

View File

@ -109,18 +109,9 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl
@Column(name = ModelConstants.EXTERNAL_ID_PROPERTY)
private UUID externalId;
@Column(name = ModelConstants.DEVICE_PROFILE_CERTIFICATE_VALUE_PROPERTY)
private String certificateValue;
@Column(name = ModelConstants.DEVICE_PROFILE_CERTIFICATE_HASH_PROPERTY)
private String certificateHash;
@Column(name = ModelConstants.DEVICE_PROFILE_CERTIFICATE_REGEX_PATTERN_PROPERTY)
private String certificateRegexPattern;
@Column(name = ModelConstants.ALLOW_CREATE_NEW_DEVICES_BY_X509_PROVISION)
private boolean allowCreateDevice;
public DeviceProfileEntity() {
super();
}
@ -139,9 +130,6 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl
this.transportType = deviceProfile.getTransportType();
this.provisionType = deviceProfile.getProvisionType();
this.certificateHash = deviceProfile.getCertificateHash();
this.certificateValue = deviceProfile.getCertificateValue();
this.certificateRegexPattern = deviceProfile.getCertificateRegexPattern();
this.allowCreateDevice = deviceProfile.isAllowCreateNewDevicesByX509Strategy();
this.description = deviceProfile.getDescription();
this.isDefault = deviceProfile.isDefault();
this.profileData = JacksonUtil.convertValue(deviceProfile.getProfileData(), ObjectNode.class);
@ -205,9 +193,6 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl
}
deviceProfile.setProvisionDeviceKey(provisionDeviceKey);
deviceProfile.setCertificateHash(certificateHash);
deviceProfile.setCertificateValue(certificateValue);
deviceProfile.setCertificateRegexPattern(certificateRegexPattern);
deviceProfile.setAllowCreateNewDevicesByX509Strategy(allowCreateDevice);
if (firmwareId != null) {
deviceProfile.setFirmwareId(new OtaPackageId(firmwareId));

View File

@ -292,12 +292,9 @@ CREATE TABLE IF NOT EXISTS device_profile (
default_dashboard_id uuid,
default_queue_name varchar(255),
provision_device_key varchar,
certificate_value varchar,
certificate_hash varchar,
certificate_regex_pattern varchar(255),
default_edge_rule_chain_id uuid,
external_id uuid,
allow_create_device_by_x509 boolean,
CONSTRAINT device_profile_credentials_hash_unq_key UNIQUE (certificate_hash),
CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name),
CONSTRAINT device_provision_key_unq_key UNIQUE (provision_device_key),