Browse Source

Changes after code review

pull/3925/head
Viacheslav Kukhtyn 6 years ago
parent
commit
fb460d7215
  1. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java
  2. 29
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CredentialsType.java
  3. 22
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java
  4. 13
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java
  5. 19
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java
  6. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttAnonymousCredentials.java
  7. 6
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttBasicCredentials.java
  8. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttCertPemCredentials.java
  9. 11
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttClientCredentials.java
  10. 28
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java
  11. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpAnonymousCredentials.java
  12. 10
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpBasicCredentials.java
  13. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpCertPemCredentials.java
  14. 14
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpClientCredentials.java
  15. 4
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/credentials/HttpBasicCredentialsTest.java

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java

@ -49,7 +49,6 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Optional;
@Data
@Slf4j
@ -62,7 +61,7 @@ public class CertPemCredentials {
private String privateKey;
private String password;
public Optional<SslContext> initSslContext() {
public SslContext initSslContext() {
try {
Security.addProvider(new BouncyCastleProvider());
SslContextBuilder builder = SslContextBuilder.forClient();
@ -72,7 +71,7 @@ public class CertPemCredentials {
if (StringUtils.hasLength(cert) && StringUtils.hasLength(privateKey)) {
builder.keyManager(createAndInitKeyManagerFactory());
}
return Optional.of(builder.build());
return builder.build();
} catch (Exception e) {
log.error("[{}:{}] Creating TLS factory failed!", caCert, cert, e);
throw new RuntimeException("Creating TLS factory failed!", e);

29
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CredentialsType.java

@ -0,0 +1,29 @@
/**
* 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.rule.engine.credentials;
public enum CredentialsType {
ANONYMOUS("anonymous"),
BASIC("basic"),
SAS("sas"),
CERT_PEM("cert.PEM");
private final String label;
CredentialsType(String label) {
this.label = label;
}
}

22
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java

@ -21,19 +21,22 @@ import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.thingsboard.mqtt.MqttClient;
import org.thingsboard.mqtt.MqttClientConfig;
import org.thingsboard.mqtt.MqttConnectResult;
import org.springframework.util.StringUtils;
import org.thingsboard.rule.engine.api.RuleNode;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNode;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import javax.net.ssl.SSLException;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -97,8 +100,7 @@ public class TbMqttNode implements TbNode {
}
protected MqttClient initClient(TbContext ctx) throws Exception {
Optional<SslContext> sslContextOpt = initSslContext();
MqttClientConfig config = sslContextOpt.isPresent() ? new MqttClientConfig(sslContextOpt.get()) : new MqttClientConfig();
MqttClientConfig config = new MqttClientConfig(getSslContext());
if (!StringUtils.isEmpty(this.mqttNodeConfiguration.getClientId())) {
config.setClientId(this.mqttNodeConfiguration.getClientId());
}
@ -125,12 +127,12 @@ public class TbMqttNode implements TbNode {
return client;
}
private Optional<SslContext> initSslContext() throws SSLException {
Optional<SslContext> result = this.mqttNodeConfiguration.getCredentials().initSslContext();
if (this.mqttNodeConfiguration.isSsl() && !result.isPresent()) {
result = Optional.of(SslContextBuilder.forClient().build());
private SslContext getSslContext() throws SSLException {
SslContext sslContext = this.mqttNodeConfiguration.getCredentials().initSslContext();
if (this.mqttNodeConfiguration.isSsl() && sslContext == null) {
sslContext = SslContextBuilder.forClient().build();
}
return result;
return sslContext;
}
}

13
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java

@ -24,6 +24,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.thingsboard.common.util.AzureIotHubUtil;
import org.thingsboard.rule.engine.credentials.CredentialsType;
import org.thingsboard.rule.engine.mqtt.credentials.MqttClientCredentials;
import javax.net.ssl.TrustManagerFactory;
@ -32,7 +33,6 @@ import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Optional;
@Data
@Slf4j
@ -42,22 +42,27 @@ public class AzureIotHubSasCredentials implements MqttClientCredentials {
private String caCert;
@Override
public Optional<SslContext> initSslContext() {
public SslContext initSslContext() {
try {
Security.addProvider(new BouncyCastleProvider());
if (caCert == null || caCert.isEmpty()) {
caCert = AzureIotHubUtil.getDefaultCaCert();
}
return Optional.of(SslContextBuilder.forClient()
return SslContextBuilder.forClient()
.trustManager(createAndInitTrustManagerFactory())
.clientAuth(ClientAuth.REQUIRE)
.build());
.build();
} catch (Exception e) {
log.error("[{}] Creating TLS factory failed!", caCert, e);
throw new RuntimeException("Creating TLS factory failed!", e);
}
}
@Override
public CredentialsType getType() {
return CredentialsType.SAS;
}
private TrustManagerFactory createAndInitTrustManagerFactory() throws Exception {
X509Certificate caCertHolder;
caCertHolder = readCertFile(caCert);

19
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java

@ -25,14 +25,13 @@ import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.rule.engine.credentials.CredentialsType;
import org.thingsboard.rule.engine.mqtt.TbMqttNode;
import org.thingsboard.rule.engine.mqtt.TbMqttNodeConfiguration;
import org.thingsboard.rule.engine.mqtt.credentials.MqttCertPemCredentials;
import org.thingsboard.rule.engine.mqtt.credentials.MqttClientCredentials;
import org.thingsboard.server.common.data.plugin.ComponentType;
import java.util.Optional;
@Slf4j
@RuleNode(
type = ComponentType.EXTERNAL,
@ -53,7 +52,18 @@ public class TbAzureIotHubNode extends TbMqttNode {
MqttClientCredentials credentials = mqttNodeConfiguration.getCredentials();
mqttNodeConfiguration.setCredentials(new MqttClientCredentials() {
@Override
public Optional<SslContext> initSslContext() {
public CredentialsType getType() {
if (credentials instanceof AzureIotHubSasCredentials) {
return CredentialsType.SAS;
} else if (credentials instanceof MqttCertPemCredentials) {
return CredentialsType.CERT_PEM;
} else {
throw new IllegalArgumentException("[" + credentials.getType() + "] is not supported!");
}
}
@Override
public SslContext initSslContext() {
if (credentials instanceof AzureIotHubSasCredentials) {
AzureIotHubSasCredentials sasCredentials = (AzureIotHubSasCredentials) credentials;
if (sasCredentials.getCaCert() == null || sasCredentials.getCaCert().isEmpty()) {
@ -82,5 +92,6 @@ public class TbAzureIotHubNode extends TbMqttNode {
this.mqttClient = initClient(ctx);
} catch (Exception e) {
throw new TbNodeException(e);
} }
}
}
}

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttAnonymousCredentials.java

@ -16,6 +16,11 @@
package org.thingsboard.rule.engine.mqtt.credentials;
import org.thingsboard.rule.engine.credentials.AnonymousCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType;
public class MqttAnonymousCredentials extends AnonymousCredentials implements MqttClientCredentials {
@Override
public CredentialsType getType() {
return CredentialsType.ANONYMOUS;
}
}

6
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttBasicCredentials.java

@ -17,8 +17,14 @@ package org.thingsboard.rule.engine.mqtt.credentials;
import org.thingsboard.mqtt.MqttClientConfig;
import org.thingsboard.rule.engine.credentials.BasicCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType;
public class MqttBasicCredentials extends BasicCredentials implements MqttClientCredentials {
@Override
public CredentialsType getType() {
return CredentialsType.BASIC;
}
@Override
public void configure(MqttClientConfig config) {
config.setUsername(getUsername());

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttCertPemCredentials.java

@ -16,6 +16,11 @@
package org.thingsboard.rule.engine.mqtt.credentials;
import org.thingsboard.rule.engine.credentials.CertPemCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType;
public class MqttCertPemCredentials extends CertPemCredentials implements MqttClientCredentials {
@Override
public CredentialsType getType() {
return CredentialsType.CERT_PEM;
}
}

11
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/credentials/MqttClientCredentials.java

@ -15,14 +15,14 @@
*/
package org.thingsboard.rule.engine.mqtt.credentials;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.netty.handler.ssl.SslContext;
import org.thingsboard.mqtt.MqttClientConfig;
import org.thingsboard.rule.engine.credentials.CredentialsType;
import org.thingsboard.rule.engine.mqtt.azure.AzureIotHubSasCredentials;
import java.util.Optional;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = MqttAnonymousCredentials.class, name = "anonymous"),
@ -30,8 +30,11 @@ import java.util.Optional;
@JsonSubTypes.Type(value = AzureIotHubSasCredentials.class, name = "sas"),
@JsonSubTypes.Type(value = MqttCertPemCredentials.class, name = "cert.PEM")})
public interface MqttClientCredentials {
default Optional<SslContext> initSslContext() {
return Optional.empty();
@JsonIgnore
CredentialsType getType();
default SslContext initSslContext() {
return null;
}
default void configure(MqttClientConfig config) {

28
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java

@ -17,6 +17,7 @@ package org.thingsboard.rule.engine.rest;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@ -44,6 +45,10 @@ import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.TbRelationTypes;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.rule.engine.credentials.CredentialsType;
import org.thingsboard.rule.engine.rest.credentials.HttpBasicCredentials;
import org.thingsboard.rule.engine.rest.credentials.HttpCertPemCredentials;
import org.thingsboard.rule.engine.rest.credentials.HttpClientCredentials;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
@ -133,7 +138,7 @@ public class TbHttpClient {
} else {
this.eventLoopGroup = new NioEventLoopGroup();
Netty4ClientHttpRequestFactory nettyFactory = new Netty4ClientHttpRequestFactory(this.eventLoopGroup);
nettyFactory.setSslContext(config.getCredentials().initSslContext().orElse(SslContextBuilder.forClient().build()));
nettyFactory.setSslContext(getSslContext(config.getCredentials()));
nettyFactory.setReadTimeout(config.getReadTimeoutMs());
httpClient = new AsyncRestTemplate(nettyFactory);
}
@ -142,6 +147,18 @@ public class TbHttpClient {
}
}
private SslContext getSslContext(HttpClientCredentials credentials) throws SSLException {
switch (credentials.getType()) {
case ANONYMOUS:
case BASIC:
return SslContextBuilder.forClient().build();
case CERT_PEM:
return ((HttpCertPemCredentials) credentials).initSslContext();
default:
throw new IllegalArgumentException("[" + credentials.getType() + "] is not supported!");
}
}
private void checkSystemProxyProperties() throws TbNodeException {
boolean useHttpProxy = !StringUtils.isEmpty(System.getProperty("http.proxyHost")) && !StringUtils.isEmpty(System.getProperty("http.proxyPort"));
boolean useHttpsProxy = !StringUtils.isEmpty(System.getProperty("https.proxyHost")) && !StringUtils.isEmpty(System.getProperty("https.proxyPort"));
@ -226,7 +243,7 @@ public class TbHttpClient {
private HttpHeaders prepareHeaders(TbMsgMetaData metaData) {
HttpHeaders headers = new HttpHeaders();
config.getHeaders().forEach((k, v) -> headers.add(TbNodeUtils.processPattern(k, metaData), TbNodeUtils.processPattern(v, metaData)));
config.getCredentials().getBasicAuthHeaderValue().ifPresent(v -> headers.add("Authorization", v));
addAuthorizationHeader(headers);
return headers;
}
@ -260,4 +277,11 @@ public class TbHttpClient {
throw new TbNodeException("Proxy port out of range:" + proxyPort);
}
}
private void addAuthorizationHeader(HttpHeaders headers) {
HttpClientCredentials credentials = config.getCredentials();
if (CredentialsType.BASIC == credentials.getType()) {
headers.add("Authorization", ((HttpBasicCredentials) credentials).getPassword());
}
}
}

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpAnonymousCredentials.java

@ -16,6 +16,11 @@
package org.thingsboard.rule.engine.rest.credentials;
import org.thingsboard.rule.engine.credentials.AnonymousCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType;
public class HttpAnonymousCredentials extends AnonymousCredentials implements HttpClientCredentials {
@Override
public CredentialsType getType() {
return CredentialsType.ANONYMOUS;
}
}

10
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpBasicCredentials.java

@ -17,15 +17,19 @@ package org.thingsboard.rule.engine.rest.credentials;
import org.apache.commons.codec.binary.Base64;
import org.thingsboard.rule.engine.credentials.BasicCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
public class HttpBasicCredentials extends BasicCredentials implements HttpClientCredentials {
@Override
public Optional<String> getBasicAuthHeaderValue() {
public CredentialsType getType() {
return CredentialsType.BASIC;
}
public String getBasicAuthHeaderValue() {
String authString = getUsername() + ":" + getPassword();
String encodedAuthString = new String(Base64.encodeBase64(authString.getBytes(StandardCharsets.UTF_8)));
return Optional.of("Basic " + encodedAuthString);
return "Basic " + encodedAuthString;
}
}

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpCertPemCredentials.java

@ -16,6 +16,11 @@
package org.thingsboard.rule.engine.rest.credentials;
import org.thingsboard.rule.engine.credentials.CertPemCredentials;
import org.thingsboard.rule.engine.credentials.CredentialsType;
public class HttpCertPemCredentials extends CertPemCredentials implements HttpClientCredentials {
@Override
public CredentialsType getType() {
return CredentialsType.CERT_PEM;
}
}

14
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/credentials/HttpClientCredentials.java

@ -15,11 +15,10 @@
*/
package org.thingsboard.rule.engine.rest.credentials;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.netty.handler.ssl.SslContext;
import java.util.Optional;
import org.thingsboard.rule.engine.credentials.CredentialsType;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@ -27,12 +26,7 @@ import java.util.Optional;
@JsonSubTypes.Type(value = HttpBasicCredentials.class, name = "basic"),
@JsonSubTypes.Type(value = HttpCertPemCredentials.class, name = "cert.PEM")})
public interface HttpClientCredentials {
default Optional<SslContext> initSslContext() {
return Optional.empty();
}
default Optional<String> getBasicAuthHeaderValue() {
return Optional.empty();
}
@JsonIgnore
CredentialsType getType();
}

4
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/credentials/HttpBasicCredentialsTest.java

@ -26,8 +26,8 @@ public class HttpBasicCredentialsTest {
HttpBasicCredentials credentials = new HttpBasicCredentials();
credentials.setUsername("testUser");
credentials.setPassword("testPwd");
Optional<String> actualHeaderValue = credentials.getBasicAuthHeaderValue();
Optional<String> expectedHeaderValue = Optional.of("Basic dGVzdFVzZXI6dGVzdFB3ZA==");
String actualHeaderValue = credentials.getBasicAuthHeaderValue();
String expectedHeaderValue = "Basic dGVzdFVzZXI6dGVzdFB3ZA==";
Assert.assertEquals(expectedHeaderValue, actualHeaderValue);
}

Loading…
Cancel
Save