sparkplug: validate namespace
This commit is contained in:
parent
6b121514fc
commit
0587933d5e
@ -57,9 +57,7 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilde
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.rule.engine.api.MailService;
|
||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
|
||||
import org.thingsboard.server.common.data.Customer;
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.DeviceProfileType;
|
||||
@ -93,7 +91,6 @@ import org.thingsboard.server.config.ThingsboardSecurityConfiguration;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.tenant.TenantProfileService;
|
||||
import org.thingsboard.server.dao.timeseries.TimeseriesService;
|
||||
import org.thingsboard.server.service.mail.TestMailService;
|
||||
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest;
|
||||
import org.thingsboard.server.service.security.auth.rest.LoginRequest;
|
||||
|
||||
|
||||
@ -67,6 +67,7 @@ import static org.thingsboard.server.transport.mqtt.util.sparkplug.MetricDataTyp
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.MetricDataType.UInt64;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.MetricDataType.UInt8;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMetricUtil.createMetric;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopicUtil.NAMESPACE;
|
||||
|
||||
/**
|
||||
* Created by nickAS21 on 12.01.23
|
||||
@ -79,7 +80,6 @@ public abstract class AbstractMqttV5ClientSparkplugTest extends AbstractMqttInte
|
||||
protected Calendar calendar = Calendar.getInstance();
|
||||
protected ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
|
||||
protected static final String NAMESPACE = "spBv1.0";
|
||||
protected static final String groupId = "SparkplugBGroupId";
|
||||
protected static final String edgeNode = "SparkpluBNode";
|
||||
protected static final String keysBdSeq = "bdSeq";
|
||||
@ -114,6 +114,14 @@ public abstract class AbstractMqttV5ClientSparkplugTest extends AbstractMqttInte
|
||||
}
|
||||
|
||||
public void clientWithCorrectNodeAccessTokenWithNDEATH(long ts, long value) throws Exception {
|
||||
IMqttToken connectionResult = clientConnectWithNDEATH(ts, value);
|
||||
MqttWireMessage response = connectionResult.getResponse();
|
||||
Assert.assertEquals(MESSAGE_TYPE_CONNACK, response.getType());
|
||||
MqttConnAck connAckMsg = (MqttConnAck) response;
|
||||
Assert.assertEquals(MqttReturnCode.RETURN_CODE_SUCCESS, connAckMsg.getReturnCode());
|
||||
}
|
||||
|
||||
public IMqttToken clientConnectWithNDEATH(long ts, long value, String... nameSpaceBad) throws Exception {
|
||||
String key = keysBdSeq;
|
||||
MetricDataType metricDataType = Int64;
|
||||
SparkplugBProto.Payload.Builder deathPayload = SparkplugBProto.Payload.newBuilder()
|
||||
@ -125,18 +133,15 @@ public abstract class AbstractMqttV5ClientSparkplugTest extends AbstractMqttInte
|
||||
this.client.setCallback(this.mqttCallback);
|
||||
MqttConnectionOptions options = new MqttConnectionOptions();
|
||||
options.setUserName(gatewayAccessToken);
|
||||
String topic = NAMESPACE + "/" + groupId + "/" + SparkplugMessageType.NDEATH.name() + "/" + edgeNode;
|
||||
String nameSpace = nameSpaceBad.length == 0 ? NAMESPACE : nameSpaceBad[0];
|
||||
String topic = nameSpace + "/" + groupId + "/" + SparkplugMessageType.NDEATH.name() + "/" + edgeNode;
|
||||
MqttMessage msg = new MqttMessage();
|
||||
msg.setId(0);
|
||||
msg.setPayload(deathBytes);
|
||||
options.setWill(topic, msg);
|
||||
IMqttToken connectionResult = client.connect(options);
|
||||
|
||||
MqttWireMessage response = connectionResult.getResponse();
|
||||
Assert.assertEquals(MESSAGE_TYPE_CONNACK, response.getType());
|
||||
MqttConnAck connAckMsg = (MqttConnAck) response;
|
||||
Assert.assertEquals(MqttReturnCode.RETURN_CODE_SUCCESS, connAckMsg.getReturnCode());
|
||||
return client.connect(options);
|
||||
}
|
||||
|
||||
protected List<Device> connectClientWithCorrectAccessTokenWithNDEATHCreatedDevices(int cntDevices, long ts) throws Exception {
|
||||
List<Device> devices = new ArrayList<>();
|
||||
clientWithCorrectNodeAccessTokenWithNDEATH();
|
||||
|
||||
@ -33,6 +33,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.thingsboard.server.common.data.DataConstants.CLIENT_SCOPE;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.MetricDataType.UInt32;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType.NCMD;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopicUtil.NAMESPACE;
|
||||
|
||||
/**
|
||||
* Created by nickAS21 on 12.01.23
|
||||
|
||||
@ -40,6 +40,7 @@ import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugConn
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugConnectionState.ONLINE;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType.STATE;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType.messageName;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopicUtil.NAMESPACE;
|
||||
|
||||
/**
|
||||
* Created by nickAS21 on 12.01.23
|
||||
@ -74,6 +75,16 @@ public abstract class AbstractMqttV5ClientSparkplugConnectionTest extends Abstra
|
||||
Assert.assertEquals(expectedReasonCode, actualException.getReasonCode());
|
||||
}
|
||||
|
||||
protected void processClientWithCorrectNodeAccessTokenNameSpaceInvalid_Test() throws Exception {
|
||||
long ts = calendar.getTimeInMillis() - PUBLISH_TS_DELTA_MS;
|
||||
long value = bdSeq = 0;
|
||||
MqttException actualException = Assert.assertThrows(MqttException.class, () -> clientConnectWithNDEATH(ts, value, "spBv1.2"));
|
||||
String expectedMessage = "Server unavailable.";
|
||||
int expectedReasonCode = 136;
|
||||
Assert.assertEquals(expectedMessage, actualException.getMessage());
|
||||
Assert.assertEquals(expectedReasonCode, actualException.getReasonCode());
|
||||
}
|
||||
|
||||
protected void processClientWithCorrectAccessTokenWithNDEATHCreatedDevices(int cntDevices) throws Exception {
|
||||
long ts = calendar.getTimeInMillis();
|
||||
connectClientWithCorrectAccessTokenWithNDEATHCreatedDevices(cntDevices, ts);
|
||||
|
||||
@ -49,6 +49,10 @@ public class MqttV5ClientSparkplugBConnectionTest extends AbstractMqttV5ClientSp
|
||||
processClientWithCorrectNodeAccessTokenWithoutNDEATH_Test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientWithCorrectNodeAccessTokenNameSpaceInvalid() throws Exception {
|
||||
processClientWithCorrectNodeAccessTokenNameSpaceInvalid_Test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientWithCorrectAccessTokenWithNDEATHCreatedOneDevice() throws Exception {
|
||||
|
||||
@ -31,6 +31,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.thingsboard.server.common.data.exception.ThingsboardErrorCode.INVALID_ARGUMENTS;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType.DCMD;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugMessageType.NCMD;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopicUtil.NAMESPACE;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractMqttV5RpcSparkplugTest extends AbstractMqttV5ClientSparkplugTest {
|
||||
|
||||
@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopicUtil.NAMESPACE;
|
||||
|
||||
/**
|
||||
* Created by nickAS21 on 12.01.23
|
||||
|
||||
@ -146,8 +146,6 @@ public enum MetricDataType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class type for this DataType
|
||||
*
|
||||
* @return the class type for this DataType
|
||||
*/
|
||||
public Class<?> getClazz() {
|
||||
|
||||
@ -25,10 +25,7 @@ public class SparkplugTopic {
|
||||
|
||||
/**
|
||||
* The Sparkplug namespace version.
|
||||
* For the Sparkplug™ A version of the payload definition, the UTF-8 string constant for the namespace element will be:
|
||||
* “spAv1.0”
|
||||
* For the Sparkplug™ B version of the specification, the UTF-8 string constant for the namespace element will be:
|
||||
* “spBv1.0”
|
||||
* For the Sparkplug™ B version of the specification, the UTF-8 string constant for the namespace element will be: “spBv1.0”
|
||||
*/
|
||||
private String namespace;
|
||||
|
||||
@ -105,9 +102,7 @@ public class SparkplugTopic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Sparkplug namespace version.
|
||||
*
|
||||
* @return the namespace
|
||||
* @return the Sparkplug namespace version
|
||||
*/
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
@ -123,17 +118,13 @@ public class SparkplugTopic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the Edge of Network (EoN) Node.
|
||||
*
|
||||
* @return the edge node ID
|
||||
* @return the ID of the Edge of Network (EoN) Node
|
||||
*/
|
||||
public String getEdgeNodeId() {
|
||||
return edgeNodeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the device.
|
||||
*
|
||||
* @return the device ID
|
||||
*/
|
||||
public String getDeviceId() {
|
||||
@ -141,8 +132,6 @@ public class SparkplugTopic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message type.
|
||||
*
|
||||
* @return the message type
|
||||
*/
|
||||
public SparkplugMessageType getType() {
|
||||
@ -162,8 +151,6 @@ public class SparkplugTopic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this topic's type matches the passes in type, false otherwise.
|
||||
*
|
||||
* @param type the type to check
|
||||
* @return true if this topic's type matches the passes in type, false otherwise
|
||||
*/
|
||||
|
||||
@ -30,6 +30,7 @@ public class SparkplugTopicUtil {
|
||||
|
||||
private static final Map<String, String[]> SPLIT_TOPIC_CACHE = new HashMap<String, String[]>();
|
||||
private static final String TOPIC_INVALID_NUMBER = "Invalid number of topic elements: ";
|
||||
public static final String NAMESPACE = "spBv1.0";
|
||||
|
||||
public static String[] getSplitTopic(String topic) {
|
||||
String[] splitTopic = SPLIT_TOPIC_CACHE.get(topic);
|
||||
@ -93,7 +94,7 @@ public class SparkplugTopicUtil {
|
||||
} else {
|
||||
SparkplugMessageType type;
|
||||
String namespace, edgeNodeId, groupId, deviceId;
|
||||
namespace = splitTopic[0];
|
||||
namespace = validateNameSpace(splitTopic[0]);
|
||||
groupId = length > 1 ? splitTopic[1] : null;
|
||||
type = length > 2 ? SparkplugMessageType.parseMessageType(splitTopic[2]) : null;
|
||||
edgeNodeId = length > 3 ? splitTopic[3] : null;
|
||||
@ -102,4 +103,14 @@ public class SparkplugTopicUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For the Sparkplug™ B version of the specification, the UTF-8 string constant for the namespace element will be: "spBv1.0"
|
||||
* @param nameSpace
|
||||
* @return
|
||||
*/
|
||||
private static String validateNameSpace(String nameSpace) throws ThingsboardException {
|
||||
if ("spBv1.0".equals(nameSpace)) return nameSpace;
|
||||
throw new ThingsboardException("The namespace [" + nameSpace + "] is not valid and must be [spBv1.0] for the Sparkplug™ B version.", ThingsboardErrorCode.INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user