AI rule node: fix flaky Azure IoT hub node test
This commit is contained in:
parent
9bcd3d8849
commit
fd7faa5a9e
@ -26,11 +26,13 @@ import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Clock;
|
||||
import java.util.Base64;
|
||||
import java.util.Iterator;
|
||||
|
||||
@Slf4j
|
||||
public final class AzureIotHubUtil {
|
||||
|
||||
private static final String BASE_DIR_PATH = System.getProperty("user.dir");
|
||||
private static final String APP_DIR = "application";
|
||||
private static final String SRC_DIR = "src";
|
||||
@ -52,41 +54,37 @@ public final class AzureIotHubUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static final long SAS_TOKEN_VALID_SECS = 365 * 24 * 60 * 60;
|
||||
private static final long ONE_SECOND_IN_MILLISECONDS = 1000;
|
||||
private static final long SAS_TOKEN_VALID_SECS = 365 * 24 * 60 * 60; // one year
|
||||
|
||||
private static final String SAS_TOKEN_FORMAT = "SharedAccessSignature sr=%s&sig=%s&se=%s";
|
||||
|
||||
private static final String USERNAME_FORMAT = "%s/%s/?api-version=2018-06-30";
|
||||
|
||||
private AzureIotHubUtil() {
|
||||
}
|
||||
private AzureIotHubUtil() {}
|
||||
|
||||
public static String buildUsername(String host, String deviceId) {
|
||||
return String.format(USERNAME_FORMAT, host, deviceId);
|
||||
}
|
||||
|
||||
public static String buildSasToken(String host, String sasKey) {
|
||||
public static String buildSasToken(String host, String sasKey, Clock clock) {
|
||||
try {
|
||||
final String targetUri = URLEncoder.encode(host.toLowerCase(), "UTF-8");
|
||||
final long expiryTime = buildExpiresOn();
|
||||
final String targetUri = URLEncoder.encode(host.toLowerCase(), StandardCharsets.UTF_8);
|
||||
final long expiryTime = buildExpiresOn(clock);
|
||||
String toSign = targetUri + "\n" + expiryTime;
|
||||
byte[] keyBytes = Base64.getDecoder().decode(sasKey.getBytes(StandardCharsets.UTF_8));
|
||||
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(signingKey);
|
||||
byte[] rawHmac = mac.doFinal(toSign.getBytes(StandardCharsets.UTF_8));
|
||||
String signature = URLEncoder.encode(Base64.getEncoder().encodeToString(rawHmac), "UTF-8");
|
||||
String signature = URLEncoder.encode(Base64.getEncoder().encodeToString(rawHmac), StandardCharsets.UTF_8);
|
||||
return String.format(SAS_TOKEN_FORMAT, targetUri, signature, expiryTime);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to build SAS token!!!", e);
|
||||
throw new RuntimeException("Failed to build SAS token!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static long buildExpiresOn() {
|
||||
long expiresOnDate = System.currentTimeMillis();
|
||||
expiresOnDate += SAS_TOKEN_VALID_SECS * ONE_SECOND_IN_MILLISECONDS;
|
||||
return expiresOnDate / ONE_SECOND_IN_MILLISECONDS;
|
||||
private static long buildExpiresOn(Clock clock) {
|
||||
return clock.instant().plusSeconds(SAS_TOKEN_VALID_SECS).getEpochSecond();
|
||||
}
|
||||
|
||||
public static String getDefaultCaCert() {
|
||||
|
||||
@ -17,6 +17,7 @@ package org.thingsboard.rule.engine.mqtt.azure;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.netty.handler.codec.mqtt.MqttVersion;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.thingsboard.common.util.AzureIotHubUtil;
|
||||
@ -36,6 +37,8 @@ import org.thingsboard.server.common.data.plugin.ComponentClusteringMode;
|
||||
import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||
import org.thingsboard.server.common.data.util.TbPair;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@Slf4j
|
||||
@RuleNode(
|
||||
type = ComponentType.EXTERNAL,
|
||||
@ -49,6 +52,8 @@ import org.thingsboard.server.common.data.util.TbPair;
|
||||
)
|
||||
public class TbAzureIotHubNode extends TbMqttNode {
|
||||
|
||||
private Clock clock = Clock.systemUTC();
|
||||
|
||||
@Override
|
||||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
||||
super.init(ctx);
|
||||
@ -73,7 +78,7 @@ public class TbAzureIotHubNode extends TbMqttNode {
|
||||
config.setUsername(AzureIotHubUtil.buildUsername(mqttNodeConfiguration.getHost(), config.getClientId()));
|
||||
ClientCredentials credentials = mqttNodeConfiguration.getCredentials();
|
||||
if (CredentialsType.SAS == credentials.getType()) {
|
||||
config.setPassword(AzureIotHubUtil.buildSasToken(mqttNodeConfiguration.getHost(), ((AzureIotHubSasCredentials) credentials).getSasKey()));
|
||||
config.setPassword(AzureIotHubUtil.buildSasToken(mqttNodeConfiguration.getHost(), ((AzureIotHubSasCredentials) credentials).getSasKey(), clock));
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +86,11 @@ public class TbAzureIotHubNode extends TbMqttNode {
|
||||
return initClient(ctx);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setClock(Clock clock) {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbPair<Boolean, JsonNode> upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
|
||||
boolean hasChanges = false;
|
||||
|
||||
@ -34,6 +34,9 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||
import org.thingsboard.rule.engine.credentials.CertPemCredentials;
|
||||
import org.thingsboard.rule.engine.mqtt.TbMqttNodeConfiguration;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -77,7 +80,10 @@ public class TbAzureIotHubNodeTest extends AbstractRuleNodeUpgradeTest {
|
||||
|
||||
@Test
|
||||
public void verifyPrepareMqttClientConfigMethodWithAzureIotHubSasCredentials() throws Exception {
|
||||
AzureIotHubSasCredentials credentials = new AzureIotHubSasCredentials();
|
||||
var fixedClock = Clock.fixed(Instant.parse("2030-01-01T00:00:00Z"), ZoneOffset.UTC);
|
||||
azureIotHubNode.setClock(fixedClock);
|
||||
|
||||
var credentials = new AzureIotHubSasCredentials();
|
||||
credentials.setSasKey("testSasKey");
|
||||
credentials.setCaCert("test-ca-cert.pem");
|
||||
azureIotHubNodeConfig.setCredentials(credentials);
|
||||
@ -89,7 +95,7 @@ public class TbAzureIotHubNodeTest extends AbstractRuleNodeUpgradeTest {
|
||||
azureIotHubNode.prepareMqttClientConfig(mqttClientConfig);
|
||||
|
||||
assertThat(mqttClientConfig.getUsername()).isEqualTo(AzureIotHubUtil.buildUsername(azureIotHubNodeConfig.getHost(), mqttClientConfig.getClientId()));
|
||||
assertThat(mqttClientConfig.getPassword()).isEqualTo(AzureIotHubUtil.buildSasToken(azureIotHubNodeConfig.getHost(), credentials.getSasKey()));
|
||||
assertThat(mqttClientConfig.getPassword()).isEqualTo(AzureIotHubUtil.buildSasToken(azureIotHubNodeConfig.getHost(), credentials.getSasKey(), fixedClock));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user