Sunday, May 29, 2016

Secure MQQT (2) with RabbitMQ

The next step has been configuring the RabbitMQ broker I have installed on my RPI to use TLS/SSL

It has worked.

The configuration file is located under /etc/rabbitmq

This is the final configuration, enabled for SSL and MQTT.

MQTT port used is 8883 (the default).

[{rabbit,        [{loopback_users,    []},

                 {ssl_options, [{cacertfile,"/etc/rabbitmq/certs/ca.crt"},

                          {certfile,  "/etc/rabbitmq/certs/server.crt"},

                          {keyfile,   "/etc/rabbitmq/certs/server.key"},

                          {password,  “<insert here>"}

                         ]}

                 ]},

 {rabbitmq_mqtt, [{default_user,     <<"guest">>},

                  {default_pass,     <<….>>},

                  {allow_anonymous,  true},

                  {vhost,            <<"/">>},

                  {exchange,         <<"amq.topic">>},

                  {subscription_ttl, 1800000},

                  {prefetch,         10},

                  {ssl_listeners,    []},

                  %% Default MQTT with TLS port is 8883

                  {ssl_listeners,    [8883]},

                  {tcp_listeners,    [1883]},

                  {tcp_listen_options, [{backlog,   128},

                                        {nodelay,   true}]}]}

].


From the RabbitMQ Web UI, accessible at the URL:


http://iotgateway1:15672/#/


you can easily monitor the flow of messages.


Some snapshot from the WebUI


NewImage

 

NewImage

 

NewImage

Saturday, May 28, 2016

Secure MQTT (TLS/SSL)

Introduction.

(Updated: 04/11/2016)
In this blog post I want to explore how to make secure the communication between an Intel Edison Board and a MQTT Broker, using Transport Layer Security (TLS).
With TLS you can make highly secure the communication between your devices and the broker, by:
  • Authenticating the board (the device) against the broker;
  • Encrypting all the the communication between the board and the broker; The channel is entirely encrypted and MQTT messages, sent over this channel, are not readable by others;
  • Protecting the integrity of messages.
TLS  is based on Public Key Encryption. For each device is generated a different public/private key-pair and the key-pair is used to protect the communication and to identify the device towards the broker. It is a widely used security mechanism, enough strong for private and commercial purposes.
Security is OK, but encryption has its costs: an higher CPU usage and high latency. It is OK if you only need to send several hundreds of bytes/sec (as with our telemetry tests). But if you need to sustain high transmission rates you need to carefully consider the overhead (I don’t think you want to send  a film streamed from the Edison, entirely encrypted, in real-time).
In a commercial/industrial scenario you would surely use certificates provided by a Trusted Provider (i.e.: Verisign). For our examples we don’t want to buy certificates and therefore we will use self-signed certificates. In other words we’re signing our certificates.

The configuration.

These are, at high level, the needed configuration steps:
  1. Generate keys and a certificate for “Our Certification Authority"
  2. Generate the key-pair for the board;
  3. Generate the key-pair for the broker;
  4. Configure the MQTT broker in order to use TLS and use the generated keys.
  5. Configure the JVM on the board and Paho client in order to use TLS and generated keys.
As we will se, it is not easy if you’re not normally involved in these kinds of configurations. But these are steps always repeated when you need to secure communication. For example, if you want to talk with AWS IoT broker, you can ONLY use TLS.
We will do the first tests using Mosquitto.
We will generate key-pair and certificates using Openssl. In my case I have openssl on My MacBook and I will generate all the files using  openssl.
A quick list of the commands to be used is found in : http://mosquitto.org/man/mosquitto-tls-7.html.
One advice: be consistent in your specification (always use the name of the server, the same company, the same Country..). You’re mimicking a certification authority that is giving certificates for your boards and server, they won’t accept “fake names”.

1. Generate keys and certificate for the Certification Authority
You're going to generate a self-signed certificate, contained in ca.crt file.

openssl req -new -x509 -days 730 -extensions v3_ca -keyout ca.key -out ca.crt
(don’t forget to remember the pass-phrase you set).

2. Generate key-pair for the board (whose name is thunder10).
openssl genrsa -des3 -out client.key 2048

openssl req -out client.csr -key client.key -new

openssl x509 -req -in client.csr -CA ../authority/ca.crt -CAkey ../authority/ca.key -CAcreateserial -out client.crt -days 730
3. Generate key-pair for the broker.

      openssl genrsa -des3 -out server.key 2048

      openssl req -out server.csr -key server.key -new

After you have generated the key-pair for the broker (iotagateway1) you need to sign the certificate assigned to the broker using the keys of the CA.
openssl x509 -req -in server.csr -CA ../authority/ca.crt -CAkey ../authority/ca.key -CAcreateserial -out server.crt -days 730
Signature ok
subject=/C=IT/ST=Italy/L=Rome/O=LSaetta/OU=IT/CN=iotgateway1/emailAddress=luigi.saetta@gmail.com
Getting CA Private Key
Enter pass phrase for ../authority/ca.key:

4. This is the configuration for the Mosquitto Broker (mosquitto.conf):
listener 8883
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1
CA certificate has been put under ca_certificates subdirectory.
Server key and certificate have been put under certs directory (these are default directories suggested by mosquitto installation, at least in RPI, which is the platform of my Broker).

You can now test the configuration sending tests messages using mosquitto_pub with this command:

mosquitto_pub -h iotgateway1 -m "Hello" -p 8883 -t thunder10 --cafile ./authority/ca.crt --key ./board/client.key --cert ./board/client.crt

<supply pem passphrase>
(whereas I have put my files under board, authority subdirectories).

5. The final part is the configuration of the JVM and the Java program in order to use SSL.

First, the String specifying the BROKER has to change to 

ssl:<broker_name>:8883

then, you have to import client key and CA certificate inside a Java Keystore.
I have used the App KeyStore Explorer.

Then, you need to add some code to the Java Client, based on Eclipse Paho 

To read the keystone:
private KeyStore readKeyStore()
{
KeyStore keystore = null;

try
{
FileInputStream is = new FileInputStream(config.KEYSTORE);

keystore = KeyStore.getInstance(KeyStore.getDefaultType());

String keypwd = config.KEYPWD;

keystore.load(is, keypwd.toCharArray());
} catch (Exception e)
{
e.printStackTrace();
}
   
    returnkeystore;
}
To add options for SSL:

// verify is SSL is requested
if (config.BROKER.contains("ssl"))
{
try
{
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = readKeyStore();
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

connOpts.setSocketFactory(sslContext.getSocketFactory());
} catch (Exception e)
{
e.printStackTrace();
System.exit(-1);
}    
}
As usual you will find all the code in my GitHub repository.


Some more comments about performances. 

As I said before, TLS has its overhead, and with constrained devices you should always consider how much additional CPU you need.
But, to be precise, the biggest overhead is in the session establishment phase, at the beginning, where client and server exchange the keys-pair and negotiate a symmetric session key, used for all the following communication.
Therefore, if your devices keeps a permanent connection, the overhead after is not so high, at least in terms of latency.

Friday, May 20, 2016

Java and Edison: Configuration, not Code

I decided to try to see if it was possible, and how difficult, to develop a configurable Java program for Intel Edison.

What do I mean as configurable?

I wanted a Java program able to run and:

1. Read a set of analog sensors connected, in a continuous loop

2. Be able to specify through a configuration file (config.properties) the type of sensors and the pins used

3. Be able to send a MQTT message to a MQTT broker, containing all the readings from sensors

4. Be able to specify the broker destination in the config file.

It is still a trial, but I succeeded. The configurable parameters are:

1. Type of sensor.

2. Pins used

3. Interval between readings

4. URL of the broker

One of the problems was that the UPM classes have not a uniform interface. For some classes the method to be used is getValue(), for others a different signature.

Therefore I have defined a Sensor Interface and a set of classes, extending the UPM class for the relative sensor and implementing the Sensor Interface.

This way all the object created for sensors are inserted in a List<ISensor> and I can literate.

The repository for the code is:

https://github.com/luigisaetta/edison-java-projects/tree/master/RoomStation

Inside you can also find an example for the config.properties.

For the tests I have used:

1. Intel Edison, with Arduino Board;

2. Grove Shield

3. Grove Temp, Grove Light and Grove TP401 Gas sensor

4. RabbitMQ MQTT broker, installed on a RPI.

This is the format of JSON msgs sent. Formatted using Google GSON library. 

{
   "id":"thunder10",
   "type":"Edison",
   "date":"May 23, 2016 9:16:13 AM",
   "readings":[
      {
         "type":"Grove.Temp",
         "unit":"C",
         "value":"25.0"
      },
      {
         "type":"Grove.Light",
         "unit":"LUX",
         "value":"324.0"
      },
      {
         "type":"Grove.TP401",
         "unit":"PPM",
         "value":"83"
      }
   ]
}
 
Nice.

Saturday, May 14, 2016

Experimenting with Docker

The nice thing with Docker is that you can easily and quickly setup an environment where you can test new products.

In my IoT Gateway the MQTT broker is Mosquitto. It works fine. But it has no monitoring interface.

I’m thinking about to test RabbitMQ as MQTT broker. It has a nice Web UI, with monitoring and admin capabilities. It is a little bit more complicated (RabbitMQ doesn’t start natively with MQTT, you need to enable a plug-in) but it can be installed on RPI.

I decided to run a quick test following my colleague G. Provinciali blog’s advice:

https://devopschannel.com/2016/05/12/docker-weblogic-e-kitematic/

I installed Docker and Kitematic GUI on my MacBook and then I downloaded Docker's official RabbitMQ image.

Then, some steps to enable MQTT and expose port 1883 and… it was working.

NewImage

and here a screenshot of RabbitMQ Web UI.

NewImage

 

As client, I have used mosquitto_sub and  Eclipse Paho GUI client. Worked fine.

Ok, next step is installation on RPI. Stay tuned.

Friday, May 13, 2016

Java, Edison, new GitHub repository

I have decided to organize the repository for the Java code in a slightly different way.

The URL to access is: 

https://github.com/luigisaetta/edison-java-projects

The first project is RoomStation, where you find Java code for:

  • using Grove Temp, Light, Air Quality sensors
  • send MQTT msg to a broker
  • formatting msg in JSON (using Google GSON)

bye.

Tuesday, May 10, 2016

Huh, should I read myself?

Sometimes I make good things.

http://lsaetta.blogspot.it/2015/04/learning-how-to-learn-my-final-work.html

Java, mon amour (again on Edison)

Yes, it is true that Java is rather old. But it is also a wonderful language.

When I started working in Java, coming from C++, it seemed to me a breeze. No problems with memory allocation, no problem with pointers. Difficult to make big mistakes. Elegant and simple.

Then, year after year, with many improvements a lot of packages and functionalities have been added.

No more simple.

It is a long and complicated discussion. Probably Java is old.

But it is really nice for me to write code in Java (well, I don’t write code as an everyday job, as it was 20 years ago, so I’m not so fast) but… it is nice.

I have discovered that it is really easy to write a program for Intel Edison, in Java, using UPM libraries to read sensors and using MQTT to communicate with an MQTT broker.

Here, in one of my github repository, you find the Java code. It took only some hours.

https://github.com/luigisaetta/edison/tree/master/src/edison

Will it work?

Yes, sure.

I’ll describe the pieces of the code in another blog post. But do I really need?

update… here is the proof that it works. The client is the Paho GUI client.

NewImage

Monday, May 9, 2016

Intel Edison and Java

I have worked for a long time with Java, and probably Java is the language that I better manage.

But, Java is not frequently used on IoT devices and boards. The main reason is that it is considered a resource hog. It requires a lot of memory.

Anyway, Intel Edison is not so resource-constrained as some other boards (Arduino), with its 1 GB Ram, and therefore it is perfectly justified the decision to try to test Java and UPM libraries to see how they works.

The development environment that I’m going to use is the one provided by Intel: The Intel Studio IoT Edition (ISS) based on Eclipse.

But, I don’t want to use the Java JDK normally distributed with Yocto (OpenJDK) and, therefore, the first step that I’m going to do is to install Oracle JDK 8 on Edison.

mkdir /usr/java

Then downloads Oracle JDK 8 on Edison; The version I have downloaded from the Oracle site is:

jdk-8u91-linux-i586.tar.gz

(be sure to download the X86 version and NOT the X86_64, Edison is 32-bit).

Then, extract the tar file with the command

tar -xvzf jdk-8u91-linux-x64.tar.gz

after, move the exploded directory under /usr/java

mv jdk1.8.0_91 /usr/java

At this point, you only need to setup correctly two environment variables

export JAVA_HOME=/usr/java/jdk1.8.0_91

 

export PATH=$JAVA_HOME/bin:$PATH


Then, you can check that Oracle Java JDK 8 is correctly installed with:

 

java -version

 

java version "1.8.0_91"

 

Java(TM) SE Runtime Environment (build 1.8.0_91-b14)

 

Java HotSpot(TM) Client VM (build 25.91-b14, mixed mode)

 

Ok, the first step is done, the JDK 8 is installed and working.

 

Now, you need to install the Java libraries for MRAA and UPM.

 

The latest version of the Java (JNI) libraries from IOTDK 3.0 can be downloaded from

 

http://iotdk.intel.com/repos/3.0/java/iotdk-java-latest.zip

 

I have downloaded this zip file, extracted the contents in 

 

/home/root/javaprograms/lib


This directory have to be put inside the classpath, when you run your program.


To test I have created a simple Java program, made by a single Java Class. The program uses two sensors from the Grove Starter Kit Plus: Temperature and Light.


import upm_grove.*;


public class Test1

{

        private static int PIN_TEMP = 0;

        private static int PIN_LIGHT = 1;

        private static int SLEEP_TIME = 3000;

       

        public static void main(String[] args)

        {

                System.out.println("Starting program...");

               

                GroveTemp tempSensor = new GroveTemp(PIN_TEMP);

                GroveLight lightSensor = new GroveLight(PIN_LIGHT);

               

                int i = 0;

                while (i < 100)

                {

                        float temp = tempSensor.value();

                        float light = lightSensor.raw_value();

                        System.out.println("Temperature is : " + temp + ", Light is: " + light);

                       

                        try

                        {

                                Thread.sleep(SLEEP_TIME);

                        } catch (InterruptedException e)

                        {

                                e.printStackTrace();

                        }

                }

        }

}


The java class is called Test1 and it is packed inside test1.jar file.


To run the program:


java -cp .:/home/root/javaprograms/lib/*:test1.jar Test1


where Test1 is the name of the main class

 

It works !!. Simple. 

 

In the next blog post, once again, I will integrate with MQTT library Paho and I will test sending msgs with readings from sensors to a Mosquitto MQTT broker.

Saturday, May 7, 2016

Now with real sensors

The hardware configuration I’m going to test consist of an Edison Board equipped with a Grove Shield to which we have connected three sensors (for now Air Quality Sensor is not used):
  • Temperature sensor, to A0
  • Light sensor, to A1
To handle reading from sensors, we will use UPM library. As we will see the Node code is simple.

IMG 0145
With the following code, we read values from sensors and send every 2 secs. (in the config) a msg to AWS IoT, containing value read for temperature (C) and light (lux).

Configuration is read from a file (config.js), whose content is:

{
"keyPath" : "/node_app_slot/certs/thunder10-private.pem.key",
"certPath" : "/node_app_slot/certs/thunder10-certificate.pem.crt",
"caPath" : "/node_app_slot/certs/root-ca.crt",
"region" : "eu-west-1",
"clientId" : "thunder10",
"sleepTime" : 2000
 }

The last piece (config.js) shows you what must be considered a best practice: Keep separated the logic from the configuration, that probably needs to be different from device to device and maybe can change more frequently. This way you need only to replace the config.js file.

The nice thing with Edison is that, if you want to change the configuration, you can simply upload the config.js file Over The Air.

Friday, May 6, 2016

Amazon AWS IoT: quick update

Since one of the communication protocol supported is MQTT, the obvious question is: can I use directly a MQTT client (in addition to the AWS SDK that we have used in the last post)?

Yes, you can.

For example, if you have some familiarity with MQTT, you probably have installed and worked with Mosquitto.

With Mosquitto you get installed two utilities that can be used to test publish and subscribe:

  • mosquitto_pub
  • mosquitto_sub

To test the transmission of a MQTT messages to your IoT gateway in AWS you need, as always, the certificate and the private key generated when you have registered your thing (the abstract representation in AWS of your device).

To publish a message:

/usr/local/bin/mosquitto_pub --cafile ./rootCA.pem --cert ./thunder10-certificate.pem.crt --key ./thunder10-private.pem.key -p 8883 -q 1 -d -t thunder10/test -m "Hello" -h A1NQFCHBXLAAH3.iot.eu-west-1.amazonaws.com

Client mosqpub/29492-MacBook-P sending CONNECT

Client mosqpub/29492-MacBook-P received CONNACK

Client mosqpub/29492-MacBook-P sending PUBLISH (d0, q1, r0, m1, 'thunder10/test', ... (5 bytes))

Client mosqpub/29492-MacBook-P received PUBACK (Mid: 1)

Client mosqpub/29492-MacBook-P sending DISCONNECT


The value you pass in the parameter -h is the hostname you have to refer to. You find it in your AWS IoT console.

-m: the value of the message (any sequence of bytes).

-p is the port

-q for the QoS; 1 means “at least once”. AWS doesn’t support “only once”.


You can easily run also a subscriber (mosquito_sub) on the same topic (in the example thunder10/test) and receive on your board (or laptop) the msg sent.


 

/usr/local/bin/mosquitto_sub --cafile ./rootCA.pem --cert ./thunder10-certificate.pem.crt --key ./thunder10-private.pem.key -p 8883 -d -t thunder10/test -h A1NQFCHBXLAAH3.iot.eu-west-1.amazonaws.com

 

Client mosqsub/29874-MacBook-P sending CONNECT

 

Client mosqsub/29874-MacBook-P received CONNACK

 

Client mosqsub/29874-MacBook-P sending SUBSCRIBE (Mid: 1, Topic: thunder10/test, QoS: 0)

 

Client mosqsub/29874-MacBook-P received SUBACK

 

Subscribed (mid: 1): 0

 

Client mosqsub/29874-MacBook-P received PUBLISH (d0, q0, r0, m0, 'thunder10/test', ... (5 bytes))

 

Hello

 

Client mosqsub/29874-MacBook-P received PUBLISH (d0, q0, r0, m0, 'thunder10/test', ... (5 bytes))

 

Hello




Thursday, May 5, 2016

Edison talk to AWS: Hello

In this post I’d like to explore, with some details, how to connect an Intel Edison Board to Amazon AWS.
This is the architecture we’re going to test:
NewImage


 The development language that I will use is JavaScript, running in NodeJS.
First, you need to have a working subscription with Amazon AWS, and you need to have provisioned AWS IoT.
Then, using AWS Console, you need to create a Thing.
I have called this thing Thunder10.
Then, you need to connect to this thing a Device. When you do this operation, you can select an SDK.
We will select NodeJS JDK.
NewImage
Then, you generate a certificate and a policy, that is attached to the thing. In this way you will create the public/private key-pair that will be used by the SDK to secure the communication.
Since it is attached to the thing, it will also ensure that your thing is recognized.
Then, you download the public/private key and the certificate. Take care that this is a one-time operation. In other words, after this step, if you don’t save the public and private key you won’t be able to retrieve them another time.
You will need to upload these files on the Edison board, in a well defined directory (you choose which one).
I have decided for /node_app_slot/certs
Then, after downloaded the keys and the certificate, you arrive to this page:

NewImage
In the page you find the information needed to setup the connection between the thing and Amazon AWS. Then you can download the SDK.
You can download the root CA certificate from here:
The SDK is based on MQTT.js. You can also install the SDK using npm. You find all the detailed instructions on the github.

To install it,
npm install aws-iot-device-sdk
After having installed the SDK and having uploaded keys and certificate to the directory chosen, you can quickly test a connection and send a ms with the following NodeJS code
var awsIot = require('aws-iot-device-sdk');
console.log('Started Test with AWS !!!');
var device = awsIot.device({
keyPath: "/node_app_slot/certs/thunder10-private.pem.key",
certPath: "/node_app_slot/certs/thunder10-certificate.pem.crt",
caPath: "/node_app_slot/certs/root-ca.crt",
clientId: "thunder10",
region: "eu-west-1"
});
device
.on('connect', function() {
console.log('connect');

});
device.publish('thunder10/test', JSON.stringify({ test_data: 1}));
take care that the program will stay on and connected waiting for… a CTRL-C.
Now, the important question is: how can I verify that my Edison (called Thunder10, has connected to AWS IoT and has successfully sent a msg.
There is a simple way:
Go to the console and use the MQTT client (yes !!!, the device is using MQTT, what else?)
NewImage

Create a client, specify a clientId and then, subscribe to the same topic you have defined in the publish invocation in the code (thunder10/test)
If everything is ok, you will see a msg on the left.

NewImage

One more thing. If you want to send messages in a loop, the code becomes
var awsIot = require('aws-iot-device-sdk');
var connected = false;
console.log('Started Test with AWS !!!');
var device = awsIot.device({
keyPath: "/node_app_slot/certs/thunder10-private.pem.key",
certPath: "/node_app_slot/certs/thunder10-certificate.pem.crt",
caPath: "/node_app_slot/certs/root-ca.crt",
clientId: "thunder10",
region: "eu-west-1"
});
device
.on('connect', function() {
console.log('connect');

connected = true;

});
function doSomething()
{
if (connected)
{
device.publish('thunder10/test', JSON.stringify({ temp: 25}));
console.log('Sent...');
}
// re-schedule executionn of publish
setTimeout(doSomething, 5000);
}
doSomething();
It is easy. In more or less 1.5 hours.
In the next post, maybe I’ll explore how to set-up a rule and invoke a Lambda function.
Another idea is to verify how it works on Azure.
Good Night baby.