thingsboard-aplcache

Merge with master

1/28/2017 9:23:27 PM

Details

diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index 4d08fe0..a3ca9d0 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -82,7 +82,8 @@ mqtt:
 # Uncomment the following lines to enable ssl for MQTT
 #  ssl:
 #    key_store: keystore/mqttserver.jks
-#    key_store_password: password
+#    key_store_password: server_ks_password
+#    key_password: server_key_password
 #    key_store_type: JKS
 
 # CoAP server parameters
diff --git a/dao/src/main/java/org/thingsboard/server/dao/EncryptionUtil.java b/dao/src/main/java/org/thingsboard/server/dao/EncryptionUtil.java
index 0ce5ac2..9a4e592 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/EncryptionUtil.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/EncryptionUtil.java
@@ -15,6 +15,7 @@
  */
 package org.thingsboard.server.dao;
 
+import com.google.common.base.CharMatcher;
 import lombok.extern.slf4j.Slf4j;
 import org.bouncycastle.crypto.digests.SHA3Digest;
 import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
@@ -28,7 +29,10 @@ public class EncryptionUtil {
     }
 
     public static String trimNewLines(String input) {
-        return input.replaceAll("\n","").replaceAll("\r","");
+        return input.replaceAll("-----BEGIN CERTIFICATE-----", "")
+                .replaceAll("-----END CERTIFICATE-----", "")
+                .replaceAll("\n","")
+                .replaceAll("\r","");
     }
 
     public static String getSha3Hash(String data) {

tools/pom.xml 4(+4 -0)

diff --git a/tools/pom.xml b/tools/pom.xml
index cbea684..53a486e 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -48,6 +48,10 @@
             <groupId>org.eclipse.paho</groupId>
             <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/tools/src/main/java/org/thingsboard/client/tools/MqttSslClient.java b/tools/src/main/java/org/thingsboard/client/tools/MqttSslClient.java
new file mode 100644
index 0000000..9b0fd2b
--- /dev/null
+++ b/tools/src/main/java/org/thingsboard/client/tools/MqttSslClient.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright © 2016-2017 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.client.tools;
+
+/**
+ * @author Valerii Sosliuk
+ * This class is intended for manual MQTT SSL Testing
+ */
+
+import com.google.common.io.Resources;
+import org.eclipse.paho.client.mqttv3.*;
+
+import javax.net.ssl.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.*;
+import java.security.cert.CertificateException;
+
+public class MqttSslClient {
+
+
+    private static final String MQTT_URL = "ssl://localhost:1883";
+
+    private static final String clientId = "MQTT_SSL_JAVA_CLIENT";
+    private static final String accessToken = "C1_TEST_TOKEN";
+    private static final String keyStoreFile = "mqttclient.jks";
+    private static final String JKS="JKS";
+    private static final String TLS="TLS";
+    private static final String CLIENT_KEYSTORE_PASSWORD = "client_ks_password";
+    private static final String CLIENT_KEY_PASSWORD = "client_key_password";
+
+    public static void main(String[] args) {
+
+        try {
+
+            URL ksUrl = Resources.getResource(keyStoreFile);
+            File ksFile = new File(ksUrl.toURI());
+            URL tsUrl = Resources.getResource(keyStoreFile);
+            File tsFile = new File(tsUrl.toURI());
+
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+
+            KeyStore trustStore = KeyStore.getInstance(JKS);
+            trustStore.load(new FileInputStream(tsFile), CLIENT_KEYSTORE_PASSWORD.toCharArray());
+            tmf.init(trustStore);
+            KeyStore ks = KeyStore.getInstance(JKS);
+
+            ks.load(new FileInputStream(ksFile), CLIENT_KEYSTORE_PASSWORD.toCharArray());
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(ks, CLIENT_KEY_PASSWORD.toCharArray());
+
+            KeyManager[] km = kmf.getKeyManagers();
+            TrustManager[] tm = tmf.getTrustManagers();
+            SSLContext sslContext = SSLContext.getInstance(TLS);
+            sslContext.init(km, tm, null);
+
+            MqttConnectOptions options = new MqttConnectOptions();
+            options.setSocketFactory(sslContext.getSocketFactory());
+            MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId);
+            client.connect(options);
+            Thread.sleep(3000);
+            MqttMessage message = new MqttMessage();
+            message.setPayload("{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4}".getBytes());
+            client.publish("v1/devices/me/telemetry", message);
+            client.disconnect();
+            System.out.println("Disconnected");
+            System.exit(0);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/src/main/shell/keygen.properties b/tools/src/main/shell/keygen.properties
index 08d6816..9435746 100644
--- a/tools/src/main/shell/keygen.properties
+++ b/tools/src/main/shell/keygen.properties
@@ -15,12 +15,22 @@
 #
 
 DOMAIN_SUFFIX="$(hostname)"
-PASSWORD="password"
+ORGANIZATIONAL_UNIT=Thingsboard
+ORGANIZATION=Thingsboard
+CITY=Piscataway
+STATE_OR_PROVINCE=NJ
+TWO_LETTER_COUNTRY_CODE=US
 
-CLIENT_TRUSTSTORE="client_truststore.pem"
-CLIENT_KEY_ALIAS="clientalias"
-CLIENT_FILE_PREFIX="mqttclient"
+SERVER_KEYSTORE_PASSWORD=server_ks_password
+SERVER_KEY_PASSWORD=server_key_password
 
 SERVER_KEY_ALIAS="serveralias"
 SERVER_FILE_PREFIX="mqttserver"
-SERVER_KEYSTORE_DIR="../../../../application/src/main/resources/keystore/"
\ No newline at end of file
+SERVER_KEYSTORE_DIR="../../../../application/src/main/resources/keystore/"
+
+CLIENT_KEYSTORE_PASSWORD=client_ks_password
+CLIENT_KEY_PASSWORD=client_key_password
+
+CLIENT_KEY_ALIAS="clientalias"
+CLIENT_FILE_PREFIX="mqttclient"
+
diff --git a/tools/src/main/shell/onewaysslmqttclient.py b/tools/src/main/shell/onewaysslmqttclient.py
index b0824e6..d06face 100644
--- a/tools/src/main/shell/onewaysslmqttclient.py
+++ b/tools/src/main/shell/onewaysslmqttclient.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 #
 # Copyright © 2016-2017 The Thingsboard Authors
 #
@@ -44,7 +43,7 @@ client.publish('v1/devices/me/attributes/request/1', "{\"clientKeys\":\"model\"}
 
 #client.tls_set(ca_certs="client_truststore.pem", certfile="mqttclient.nopass.pem", keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
 #               tls_version=ssl.PROTOCOL_TLSv1, ciphers=None);
-client.tls_set(ca_certs="client_truststore.pem", certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
+client.tls_set(ca_certs="mqttserver.pub.pem", certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
                        tls_version=ssl.PROTOCOL_TLSv1, ciphers=None);
 
 client.username_pw_set("B1_TEST_TOKEN")
diff --git a/tools/src/main/shell/securemqttclient.keygen.sh b/tools/src/main/shell/securemqttclient.keygen.sh
index 4d986cd..f69dd52 100755
--- a/tools/src/main/shell/securemqttclient.keygen.sh
+++ b/tools/src/main/shell/securemqttclient.keygen.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # Copyright © 2016-2017 The Thingsboard Authors
 #
@@ -17,7 +17,7 @@
 
 usage() {
     echo "This script generates client public/private rey pair, extracts them to a no-password RSA pem file,"
-    echo "and also imports server public key to client trust store"
+    echo "and imports server public key to client keystore"
     echo "usage: ./securemqttclient.keygen.sh [-p file]"
     echo "    -p | --props | --properties file  Properties file. default value is ./keygen.properties"
 	echo "    -h | --help  | ?                  Show this message"
@@ -44,17 +44,44 @@ done
 
 . $PROPERTIES_FILE
 
+if [ -f $CLIENT_FILE_PREFIX.jks ] || [ -f $CLIENT_FILE_PREFIX.pub.pem ] || [ -f $CLIENT_FILE_PREFIX.nopass.pem ] || [ -f $CLIENT_FILE_PREFIX.pem ] || [ -f $CLIENT_FILE_PREFIX.p12 ];
+then
+while :
+   do
+       read -p "Output files from previous server.keygen.sh script run found. Overwrite?[yes]" response
+       case $response in
+        [nN]|[nN][oO])
+            echo "Skipping"
+            echo "Done"
+            exit 0
+            ;;
+        [yY]|[yY][eE]|[yY][eE]|[sS]|[yY]|"")
+            echo "Cleaning up files"
+            rm -rf $CLIENT_FILE_PREFIX.jks
+            rm -rf $CLIENT_FILE_PREFIX.pub.pem
+            rm -rf $CLIENT_FILE_PREFIX.nopass.pem
+            rm -rf $CLIENT_FILE_PREFIX.pem
+            rm -rf $CLIENT_FILE_PREFIX.p12
+            break;
+            ;;
+        *)  echo "Please reply 'yes' or 'no'"
+            ;;
+        esac
+    done
+fi
+
 echo "Generating SSL Key Pair..."
 
 keytool -genkeypair -v \
   -alias $CLIENT_KEY_ALIAS \
   -dname "CN=$DOMAIN_SUFFIX, OU=Thingsboard, O=Thingsboard, L=Piscataway, ST=NJ, C=US" \
   -keystore $CLIENT_FILE_PREFIX.jks \
-  -keypass $PASSWORD \
-  -storepass $PASSWORD \
+  -keypass $CLIENT_KEY_PASSWORD \
+  -storepass $CLIENT_KEYSTORE_PASSWORD \
   -keyalg RSA \
   -keysize 2048 \
   -validity 9999
+
 echo "Converting keystore to pkcs12"
 keytool -importkeystore  \
   -srckeystore $CLIENT_FILE_PREFIX.jks \
@@ -62,28 +89,33 @@ keytool -importkeystore  \
   -srcalias $CLIENT_KEY_ALIAS \
   -srcstoretype jks \
   -deststoretype pkcs12 \
-  -keypass $PASSWORD \
-  -srcstorepass $PASSWORD \
-  -deststorepass $PASSWORD \
-  -srckeypass $PASSWORD \
-  -destkeypass $PASSWORD
+  -srcstorepass $CLIENT_KEYSTORE_PASSWORD \
+  -deststorepass $CLIENT_KEY_PASSWORD \
+  -srckeypass $CLIENT_KEY_PASSWORD \
+  -destkeypass $CLIENT_KEY_PASSWORD
 
 echo "Converting pkcs12 to pem"
 openssl pkcs12 -in $CLIENT_FILE_PREFIX.p12 \
   -out $CLIENT_FILE_PREFIX.pem \
-  -passin pass:$PASSWORD \
-  -passout pass:$PASSWORD \
+  -passin pass:$CLIENT_KEY_PASSWORD \
+  -passout pass:$CLIENT_KEY_PASSWORD \
 
-echo "Importing server public key..."
-keytool -export \
-  -alias $SERVER_KEY_ALIAS \
-  -keystore $SERVER_KEYSTORE_DIR/$SERVER_FILE_PREFIX.jks \
-  -file $CLIENT_TRUSTSTORE -rfc \
-  -storepass $PASSWORD
+echo "Importing server public key to $CLIENT_FILE_PREFIX.jks"
+keytool --importcert \
+   -file $SERVER_FILE_PREFIX.cer \
+   -keystore $CLIENT_FILE_PREFIX.jks \
+   -alias $SERVER_KEY_ALIAS \
+   -keypass $SERVER_KEY_PASSWORD \
+   -storepass $CLIENT_KEYSTORE_PASSWORD \
+   -noprompt
 
 echo "Exporting no-password pem certificate"
-openssl rsa -in $CLIENT_FILE_PREFIX.pem -out $CLIENT_FILE_PREFIX.nopass.pem -passin pass:$PASSWORD
+openssl rsa -in $CLIENT_FILE_PREFIX.pem -out $CLIENT_FILE_PREFIX.nopass.pem -passin pass:$CLIENT_KEY_PASSWORD
 tail -n +$(($(grep -m1 -n -e '-----BEGIN CERTIFICATE' $CLIENT_FILE_PREFIX.pem | cut -d: -f1) )) \
   $CLIENT_FILE_PREFIX.pem >> $CLIENT_FILE_PREFIX.nopass.pem
 
+echo "Exporting client public key"
+tail -n +$(($(grep -m1 -n -e '-----BEGIN CERTIFICATE' $CLIENT_FILE_PREFIX.pem | cut -d: -f1) )) \
+  $CLIENT_FILE_PREFIX.pem >> $CLIENT_FILE_PREFIX.pub.pem
+
 echo "Done."
\ No newline at end of file
diff --git a/tools/src/main/shell/simplemqttclient.py b/tools/src/main/shell/simplemqttclient.py
index 9ec3250..5f511f4 100644
--- a/tools/src/main/shell/simplemqttclient.py
+++ b/tools/src/main/shell/simplemqttclient.py
@@ -41,7 +41,7 @@ client.on_connect = on_connect
 client.on_message = on_message
 client.publish('v1/devices/me/attributes/request/1', "{\"clientKeys\":\"model\"}", 1)
 
-client.username_pw_set("TEST_TOKEN")
+client.username_pw_set("B1_TEST_TOKEN")
 client.connect('127.0.0.1', 1883, 1)
 
 # Blocking call that processes network traffic, dispatches callbacks and
diff --git a/tools/src/main/shell/twowaysslmqttclient.py b/tools/src/main/shell/twowaysslmqttclient.py
index d51df36..a2fa8b6 100644
--- a/tools/src/main/shell/twowaysslmqttclient.py
+++ b/tools/src/main/shell/twowaysslmqttclient.py
@@ -42,7 +42,7 @@ client.on_connect = on_connect
 client.on_message = on_message
 client.publish('v1/devices/me/attributes/request/1', "{\"clientKeys\":\"model\"}", 1)
 
-client.tls_set(ca_certs="client_truststore.pem", certfile="mqttclient.nopass.pem", keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
+client.tls_set(ca_certs="mqttserver.pub.pem", certfile="mqttclient.nopass.pem", keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
                        tls_version=ssl.PROTOCOL_TLSv1, ciphers=None);
 
 client.tls_insecure_set(False)
diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml
index 6fbb1a3..a491226 100644
--- a/transport/mqtt/pom.xml
+++ b/transport/mqtt/pom.xml
@@ -64,11 +64,9 @@
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
         </dependency>
-        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>18.0</version>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
diff --git a/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java b/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java
index da478eb..80e4e01 100644
--- a/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java
+++ b/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java
@@ -49,9 +49,11 @@ public class MqttSslHandlerProvider {
     private String keyStoreFile;
     @Value("${mqtt.ssl.key_store_password}")
     private String keyStorePassword;
+    @Value("${mqtt.ssl.key_password}")
+    private String keyPassword;
     @Value("${mqtt.ssl.key_store_type}")
     private String keyStoreType;
-
+    
     @Autowired
     private DeviceCredentialsService deviceCredentialsService;
 
@@ -72,7 +74,7 @@ public class MqttSslHandlerProvider {
 
             ks.load(new FileInputStream(ksFile), keyStorePassword.toCharArray());
             KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-            kmf.init(ks, keyStorePassword.toCharArray());
+            kmf.init(ks, keyPassword.toCharArray());
 
             KeyManager[] km = kmf.getKeyManagers();
             TrustManager x509wrapped = getX509TrustManager(tmFactory);
diff --git a/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/SslUtil.java b/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/SslUtil.java
index d1ea59b..adda344 100644
--- a/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/SslUtil.java
+++ b/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/SslUtil.java
@@ -16,6 +16,7 @@
 package org.thingsboard.server.transport.mqtt.util;
 
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.Base64Utils;
 import org.thingsboard.server.dao.EncryptionUtil;
 import sun.misc.BASE64Encoder;
 
@@ -35,17 +36,13 @@ public class SslUtil {
 
     public static String getX509CertificateString(X509Certificate cert)
             throws CertificateEncodingException, IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        BASE64Encoder encoder = new BASE64Encoder();
-        encoder.encodeBuffer(cert.getEncoded(), out);
-        return EncryptionUtil.trimNewLines(new String(out.toByteArray(), "UTF-8"));
+        Base64Utils.encodeToString(cert.getEncoded());
+        return EncryptionUtil.trimNewLines(Base64Utils.encodeToString(cert.getEncoded()));
     }
 
     public static String getX509CertificateString(javax.security.cert.X509Certificate cert)
             throws javax.security.cert.CertificateEncodingException, IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        BASE64Encoder encoder = new BASE64Encoder();
-        encoder.encodeBuffer(cert.getEncoded(), out);
-        return EncryptionUtil.trimNewLines(new String(out.toByteArray(), "UTF-8"));
+        Base64Utils.encodeToString(cert.getEncoded());
+        return EncryptionUtil.trimNewLines(Base64Utils.encodeToString(cert.getEncoded()));
     }
 }