refactored LwM2M client credentials for the new UI

This commit is contained in:
YevhenBondarenko 2021-05-18 17:30:01 +03:00 committed by Andrew Shvayka
parent 552a1efb23
commit 4cd59674ee
15 changed files with 165 additions and 100 deletions

View File

@ -151,7 +151,7 @@ public class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest {
parameterSpec); parameterSpec);
KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec); KeySpec privateKeySpec = new ECPrivateKeySpec(new BigInteger(privateS), parameterSpec);
// // Get keys // Get keys
serverPublicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec); serverPublicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);
serverPrivateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec); serverPrivateKey = KeyFactory.getInstance("EC").generatePrivate(privateKeySpec);

View File

@ -36,7 +36,7 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate;
import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd;
import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient;
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
import org.thingsboard.server.transport.lwm2m.secure.credentials.NoSecClientCredentialsConfig; import org.thingsboard.server.common.data.device.credentials.lwm2m.NoSecClientCredentials;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -112,10 +112,10 @@ public class NoSecLwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId()); Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId());
deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS); deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS);
deviceCredentials.setCredentialsId(deviceAEndpoint);
LwM2MCredentials noSecCredentials = new LwM2MCredentials(); LwM2MCredentials noSecCredentials = new LwM2MCredentials();
noSecCredentials.setClient(new NoSecClientCredentialsConfig()); NoSecClientCredentials clientCredentials = new NoSecClientCredentials();
clientCredentials.setEndpoint(deviceAEndpoint);
noSecCredentials.setClient(clientCredentials);
deviceCredentials.setCredentialsValue(JacksonUtil.toString(noSecCredentials)); deviceCredentials.setCredentialsValue(JacksonUtil.toString(noSecCredentials));
doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk());
return device; return device;

View File

@ -22,6 +22,7 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials;
import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataPageLink; import org.thingsboard.server.common.data.query.EntityDataPageLink;
import org.thingsboard.server.common.data.query.EntityDataQuery; import org.thingsboard.server.common.data.query.EntityDataQuery;
@ -37,7 +38,6 @@ import org.thingsboard.server.service.telemetry.cmd.v2.EntityDataUpdate;
import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd; import org.thingsboard.server.service.telemetry.cmd.v2.LatestValueCmd;
import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient; import org.thingsboard.server.transport.lwm2m.client.LwM2MTestClient;
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
import org.thingsboard.server.transport.lwm2m.secure.credentials.X509ClientCredentialsConfig;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -101,7 +101,7 @@ public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
private final String serverUri = "coaps://localhost:" + port; private final String serverUri = "coaps://localhost:" + port;
@NotNull @NotNull
private Device createDevice(String credentialsId, X509ClientCredentialsConfig credentialsConfig) throws Exception { private Device createDevice(X509ClientCredentials clientCredentials) throws Exception {
Device device = new Device(); Device device = new Device();
device.setName("Device A"); device.setName("Device A");
device.setDeviceProfileId(deviceProfile.getId()); device.setDeviceProfileId(deviceProfile.getId());
@ -114,13 +114,11 @@ public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId()); Assert.assertEquals(device.getId(), deviceCredentials.getDeviceId());
deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS); deviceCredentials.setCredentialsType(DeviceCredentialsType.LWM2M_CREDENTIALS);
deviceCredentials.setCredentialsId(credentialsId); LwM2MCredentials credentials = new LwM2MCredentials();
LwM2MCredentials X509Credentials = new LwM2MCredentials(); credentials.setClient(clientCredentials);
X509Credentials.setClient(credentialsConfig); deviceCredentials.setCredentialsValue(JacksonUtil.toString(credentials));
deviceCredentials.setCredentialsValue(JacksonUtil.toString(X509Credentials));
doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk()); doPost("/api/device/credentials", deviceCredentials).andExpect(status().isOk());
return device; return device;
} }
@ -128,8 +126,9 @@ public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
@Test @Test
public void testConnectAndObserveTelemetry() throws Exception { public void testConnectAndObserveTelemetry() throws Exception {
createDeviceProfile(TRANSPORT_CONFIGURATION); createDeviceProfile(TRANSPORT_CONFIGURATION);
X509ClientCredentials credentials = new X509ClientCredentials();
Device device = createDevice(endpoint, new X509ClientCredentialsConfig(null, null)); credentials.setEndpoint(endpoint);
Device device = createDevice(credentials);
SingleEntityFilter sef = new SingleEntityFilter(); SingleEntityFilter sef = new SingleEntityFilter();
sef.setSingleEntity(device.getId()); sef.setSingleEntity(device.getId());
@ -166,7 +165,10 @@ public class X509LwM2MIntegrationTest extends AbstractLwM2MIntegrationTest {
@Test @Test
public void testConnectWithCertAndObserveTelemetry() throws Exception { public void testConnectWithCertAndObserveTelemetry() throws Exception {
createDeviceProfile(TRANSPORT_CONFIGURATION); createDeviceProfile(TRANSPORT_CONFIGURATION);
Device device = createDevice(null, new X509ClientCredentialsConfig(SslUtil.getCertificateString(clientX509CertNotTrusted), endpoint)); X509ClientCredentials credentials = new X509ClientCredentials();
credentials.setEndpoint(endpoint);
credentials.setCert(SslUtil.getCertificateString(clientX509CertNotTrusted));
Device device = createDevice(credentials);
SingleEntityFilter sef = new SingleEntityFilter(); SingleEntityFilter sef = new SingleEntityFilter();
sef.setSingleEntity(device.getId()); sef.setSingleEntity(device.getId());

View File

@ -13,20 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.common.data.device.credentials.lwm2m;
import lombok.Data; import lombok.Getter;
import org.eclipse.leshan.core.SecurityMode; import lombok.NoArgsConstructor;
import lombok.Setter;
import static org.eclipse.leshan.core.SecurityMode.PSK; @Getter
@Setter
@Data @NoArgsConstructor
public class PSKClientCredentialsConfig extends HasKey implements LwM2MClientCredentialsConfig { public abstract class AbstractLwM2MClientCredentials implements LwM2MClientCredentials {
private String identity;
private String endpoint; private String endpoint;
@Override
public SecurityMode getSecurityConfigClientMode() {
return PSK;
}
} }

View File

@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.common.data.device.credentials.lwm2m;
import org.eclipse.leshan.core.util.Hex; import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Hex;
public class HasKey { public abstract class HasKey extends AbstractLwM2MClientCredentials {
private byte[] key; private byte[] key;
@SneakyThrows
public void setKey(String key) { public void setKey(String key) {
if (key != null) { if (key != null) {
this.key = Hex.decodeHex(key.toLowerCase().toCharArray()); this.key = Hex.decodeHex(key.toLowerCase().toCharArray());

View File

@ -13,25 +13,24 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.common.data.device.credentials.lwm2m;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.eclipse.leshan.core.SecurityMode;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.NAME,
property = "securityConfigClientMode") property = "securityConfigClientMode")
@JsonSubTypes({ @JsonSubTypes({
@JsonSubTypes.Type(value = NoSecClientCredentialsConfig.class, name = "NO_SEC"), @JsonSubTypes.Type(value = NoSecClientCredentials.class, name = "NO_SEC"),
@JsonSubTypes.Type(value = PSKClientCredentialsConfig.class, name = "PSK"), @JsonSubTypes.Type(value = PSKClientCredentials.class, name = "PSK"),
@JsonSubTypes.Type(value = RPKClientCredentialsConfig.class, name = "RPK"), @JsonSubTypes.Type(value = RPKClientCredentials.class, name = "RPK"),
@JsonSubTypes.Type(value = X509ClientCredentialsConfig.class, name = "X509")}) @JsonSubTypes.Type(value = X509ClientCredentials.class, name = "X509")})
public interface LwM2MClientCredentialsConfig { public interface LwM2MClientCredentials {
@JsonIgnore @JsonIgnore
SecurityMode getSecurityConfigClientMode(); LwM2MSecurityMode getSecurityConfigClientMode();
String getEndpoint();
} }

View File

@ -0,0 +1,20 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.credentials.lwm2m;
public enum LwM2MSecurityMode {
PSK, RPK, X509, NO_SEC;
}

View File

@ -13,24 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.common.data.device.credentials.lwm2m;
import lombok.AllArgsConstructor; public class NoSecClientCredentials extends AbstractLwM2MClientCredentials {
import lombok.Data;
import lombok.NoArgsConstructor;
import org.eclipse.leshan.core.SecurityMode;
import static org.eclipse.leshan.core.SecurityMode.X509;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class X509ClientCredentialsConfig implements LwM2MClientCredentialsConfig {
private String cert;
private String endpoint;
@Override @Override
public SecurityMode getSecurityConfigClientMode() { public LwM2MSecurityMode getSecurityConfigClientMode() {
return X509; return LwM2MSecurityMode.NO_SEC;
} }
} }

View File

@ -13,16 +13,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.common.data.device.credentials.lwm2m;
import org.eclipse.leshan.core.SecurityMode; import lombok.Getter;
import lombok.Setter;
import static org.eclipse.leshan.core.SecurityMode.NO_SEC; @Getter
@Setter
public class NoSecClientCredentialsConfig implements LwM2MClientCredentialsConfig { public class PSKClientCredentials extends HasKey {
private String identity;
@Override @Override
public SecurityMode getSecurityConfigClientMode() { public LwM2MSecurityMode getSecurityConfigClientMode() {
return NO_SEC; return LwM2MSecurityMode.PSK;
} }
} }

View File

@ -0,0 +1,24 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.credentials.lwm2m;
public class RPKClientCredentials extends HasKey {
@Override
public LwM2MSecurityMode getSecurityConfigClientMode() {
return LwM2MSecurityMode.RPK;
}
}

View File

@ -13,16 +13,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.common.data.device.credentials.lwm2m;
import org.eclipse.leshan.core.SecurityMode; import lombok.Getter;
import lombok.Setter;
import static org.eclipse.leshan.core.SecurityMode.RPK; @Getter
@Setter
public class RPKClientCredentialsConfig extends HasKey implements LwM2MClientCredentialsConfig { public class X509ClientCredentials extends AbstractLwM2MClientCredentials {
private String cert;
@Override @Override
public SecurityMode getSecurityConfigClientMode() { public LwM2MSecurityMode getSecurityConfigClientMode() {
return RPK; return LwM2MSecurityMode.X509;
} }
} }

View File

@ -17,21 +17,21 @@ package org.thingsboard.server.transport.lwm2m.secure;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.SecurityMode;
import org.eclipse.leshan.core.util.SecurityUtil; import org.eclipse.leshan.core.util.SecurityUtil;
import org.eclipse.leshan.server.security.SecurityInfo; import org.eclipse.leshan.server.security.SecurityInfo;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
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;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
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.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MClientCredentialsConfig; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
import org.thingsboard.server.transport.lwm2m.secure.credentials.PSKClientCredentialsConfig; import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredentials;
import org.thingsboard.server.transport.lwm2m.secure.credentials.RPKClientCredentialsConfig; import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCredentials;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
@ -97,8 +97,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
if (credentials != null) { if (credentials != null) {
if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) { if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) {
result.setBootstrapCredentialConfig(credentials.getBootstrap()); result.setBootstrapCredentialConfig(credentials.getBootstrap());
if (SecurityMode.PSK.equals(credentials.getClient().getSecurityConfigClientMode())) { if (LwM2MSecurityMode.PSK.equals(credentials.getClient().getSecurityConfigClientMode())) {
PSKClientCredentialsConfig pskClientConfig = (PSKClientCredentialsConfig) credentials.getClient(); PSKClientCredentials pskClientConfig = (PSKClientCredentials) credentials.getClient();
endpoint = StringUtils.isNotEmpty(pskClientConfig.getEndpoint()) ? pskClientConfig.getEndpoint() : endpoint; endpoint = StringUtils.isNotEmpty(pskClientConfig.getEndpoint()) ? pskClientConfig.getEndpoint() : endpoint;
} }
result.setEndpoint(endpoint); result.setEndpoint(endpoint);
@ -130,8 +130,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
result.setSecurityMode(NO_SEC); result.setSecurityMode(NO_SEC);
} }
private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentialsConfig clientCredentialsConfig) { private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
PSKClientCredentialsConfig pskConfig = (PSKClientCredentialsConfig) clientCredentialsConfig; PSKClientCredentials pskConfig = (PSKClientCredentials) clientCredentialsConfig;
if (StringUtils.isNotEmpty(pskConfig.getIdentity())) { if (StringUtils.isNotEmpty(pskConfig.getIdentity())) {
try { try {
if (pskConfig.getKey() != null && pskConfig.getKey().length > 0) { if (pskConfig.getKey() != null && pskConfig.getKey().length > 0) {
@ -149,8 +149,8 @@ public class LwM2mCredentialsSecurityInfoValidator {
} }
} }
private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentialsConfig clientCredentialsConfig) { private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
RPKClientCredentialsConfig rpkConfig = (RPKClientCredentialsConfig) clientCredentialsConfig; RPKClientCredentials rpkConfig = (RPKClientCredentials) clientCredentialsConfig;
try { try {
if (rpkConfig.getKey() != null) { if (rpkConfig.getKey() != null) {
PublicKey key = SecurityUtil.publicKey.decode(rpkConfig.getKey()); PublicKey key = SecurityUtil.publicKey.decode(rpkConfig.getKey());
@ -164,7 +164,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
} }
} }
private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentialsConfig clientCredentialsConfig) { private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint, LwM2MClientCredentials clientCredentialsConfig) {
result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint)); result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint));
result.setSecurityMode(X509); result.setSecurityMode(X509);
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.thingsboard.server.transport.lwm2m.secure; package org.thingsboard.server.transport.lwm2m.secure;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.elements.util.CertPathUtil; import org.eclipse.californium.elements.util.CertPathUtil;
@ -30,12 +29,12 @@ import org.eclipse.californium.scandium.dtls.HandshakeResultHandler;
import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier; import org.eclipse.californium.scandium.dtls.x509.NewAdvancedCertificateVerifier;
import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier; import org.eclipse.californium.scandium.dtls.x509.StaticCertificateVerifier;
import org.eclipse.californium.scandium.util.ServerNames; import org.eclipse.californium.scandium.util.ServerNames;
import org.eclipse.leshan.core.SecurityMode;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
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;
@ -44,7 +43,7 @@ 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.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials;
import org.thingsboard.server.transport.lwm2m.secure.credentials.X509ClientCredentialsConfig; import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -140,10 +139,10 @@ public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVer
ValidateDeviceCredentialsResponse msg = deviceCredentialsResponse[0]; ValidateDeviceCredentialsResponse msg = deviceCredentialsResponse[0];
if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) { if (msg != null && org.thingsboard.server.common.data.StringUtils.isNotEmpty(msg.getCredentials())) {
LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class); LwM2MCredentials credentials = JacksonUtil.fromString(msg.getCredentials(), LwM2MCredentials.class);
if(!credentials.getClient().getSecurityConfigClientMode().equals(SecurityMode.X509)){ if(!credentials.getClient().getSecurityConfigClientMode().equals(LwM2MSecurityMode.X509)){
continue; continue;
} }
X509ClientCredentialsConfig config = (X509ClientCredentialsConfig) credentials.getClient(); X509ClientCredentials config = (X509ClientCredentials) credentials.getClient();
String certBody = config.getCert(); String certBody = config.getCert();
String endpoint = config.getEndpoint(); String endpoint = config.getEndpoint();
if (strCert.equals(certBody)) { if (strCert.equals(certBody)) {

View File

@ -16,10 +16,11 @@
package org.thingsboard.server.transport.lwm2m.secure.credentials; package org.thingsboard.server.transport.lwm2m.secure.credentials;
import lombok.Data; import lombok.Data;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;
import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig; import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2MBootstrapConfig;
@Data @Data
public class LwM2MCredentials { public class LwM2MCredentials {
private LwM2MClientCredentialsConfig client; private LwM2MClientCredentials client;
private LwM2MBootstrapConfig bootstrap; private LwM2MBootstrapConfig bootstrap;
} }

View File

@ -16,7 +16,6 @@
package org.thingsboard.server.dao.device; package org.thingsboard.server.dao.device;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
@ -28,6 +27,9 @@ import org.springframework.util.StringUtils;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;
import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredentials;
import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -133,7 +135,6 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen
deviceCredentials.setCredentialsValue(JacksonUtil.toString(mqttCredentials)); deviceCredentials.setCredentialsValue(JacksonUtil.toString(mqttCredentials));
} }
private void formatCertData(DeviceCredentials deviceCredentials) { private void formatCertData(DeviceCredentials deviceCredentials) {
String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue());
String sha3Hash = EncryptionUtil.getSha3Hash(cert); String sha3Hash = EncryptionUtil.getSha3Hash(cert);
@ -142,18 +143,48 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen
} }
private void formatSimpleLwm2mCredentials(DeviceCredentials deviceCredentials) { private void formatSimpleLwm2mCredentials(DeviceCredentials deviceCredentials) {
ObjectNode json = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), ObjectNode.class); LwM2MClientCredentials clientCredentials;
JsonNode client = json.get("client"); ObjectNode json;
if (client != null && client.get("securityConfigClientMode").asText().equals("X509") && client.has("cert")) { try {
JsonNode certJson = client.get("cert"); json = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), ObjectNode.class);
if (!certJson.isNull()) { if (json == null) {
String cert = EncryptionUtil.trimNewLines(certJson.asText()); throw new IllegalArgumentException();
String sha3Hash = EncryptionUtil.getSha3Hash(cert);
deviceCredentials.setCredentialsId(sha3Hash);
((ObjectNode) client).put("cert", cert);
deviceCredentials.setCredentialsValue(JacksonUtil.toString(json));
} }
clientCredentials = JacksonUtil.convertValue(json.get("client"), LwM2MClientCredentials.class);
if (clientCredentials == null) {
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException e) {
throw new DataValidationException("Invalid credentials body for LwM2M credentials!");
} }
String credentialsId;
switch (clientCredentials.getSecurityConfigClientMode()) {
case NO_SEC:
case RPK:
credentialsId = clientCredentials.getEndpoint();
break;
case PSK:
credentialsId = ((PSKClientCredentials) clientCredentials).getIdentity();
break;
case X509:
X509ClientCredentials x509Config = (X509ClientCredentials) clientCredentials;
if (x509Config.getCert() != null) {
String cert = EncryptionUtil.trimNewLines(x509Config.getCert());
String sha3Hash = EncryptionUtil.getSha3Hash(cert);
x509Config.setCert(cert);
((ObjectNode) json.get("client")).put("cert", cert);
deviceCredentials.setCredentialsValue(JacksonUtil.toString(json));
credentialsId = sha3Hash;
} else {
credentialsId = x509Config.getEndpoint();
}
break;
default:
throw new DataValidationException("Invalid credentials body for LwM2M credentials!");
}
deviceCredentials.setCredentialsId(credentialsId);
} }
@Override @Override