Saturday, March 25, 2017

Disable SSL Certificate Validation in Java

In the previous post we saw how to disable hostname verification, here. On similar lines, we can also disable SSL cert validation in Java client.


By design when client uses JSSE implementation of the SSL protocol to perform few validations to ensure the requested host is not fake. This involves validation of the server’s X.509 certificate with the PKIX algorithm and checking the host name against the certificate subject. If the SSL certificate is not validate or does not match the target host, you will get SSLHandshakeException or IOException.

Certificate validation can be disabled by overriding default TrustManager implementation.

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType) {

            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {

            }

   } };

                

   SSLContext sc = null;

        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
   HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


References:

http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html---- 


Overriding Hostname verification of Https in Java

Java SSL library by default does hostname verification as well during certificate validation.

Remember that SSL/TLS has 2 mandates-

  • Ensure that client is talking to the server which it should be talking to (IDENTITY)
  • Communication is secure between client and server (SECURITY)
So IDENTITY validation is an important aspect of SSL handshake. Java provides an interface HostnameVerifier to ensure that hostname in the server certificate is correct. 

There might be a situation when you want to override the hostname verification in your SSL handshake. This is handy when service doesn't have a hostname, i.e it has IP address like https://10.20.30.40:8080/customService

In this case, server certificate will not have IP address as verified host name. 

To override this verification, we can return true in the custom implementation of hostname verification as shown below.

HostnameVerifier hostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            //HostnameVerifier hv =
             //       HttpsURLConnection.getDefaultHostnameVerifier();
            //return hv.verify("hostname", session);
              return true;
        }
    };

clientLibrary.setHostnameVerifier(hostnameVerifier);

If you want to see sample certificate, check out this link

Understanding Consistency in Distributed Databases

In Distributed DBs, Consistency is evaluated based on CAP theorem. This post doesn't go into CP vs AP debate of CAP, but just address what consistency means in Distributed DBs. It starts with ideal scenario and then concludes with practically possible consistency level.


In perfect world, a distributed database system will be considered Consistent if an update is applied to all nodes at same logical time, i.e. it's instantaneous and global just like updating a DB with single node.


As shown above, client makes call to insert data and then DB initiates insertion to all data nodes (primary and replica) at same time. And because all nodes are similar so they take exactly same time to insert record. Is it possible ? 

You might argue that, all nodes should be able to perform the operation in same time; so it's possible. 

If you still feel this is possible - think hard. We are talking about distributed DB, which means they are at different places. All, sorts of things are possible while communicating - hardware might fail, network connectivity might fail or slow down.
How you synchronize, if update on one node fails ?

Perfect world is impossible for distributed DB !


In Practical world, a distributed database system is considered consistent if it applies update to all nodes in a synchronized way and then confirms to the client that update is successful. So, if there is one primary nodes and 2 replicas. Then DB should make sure that replicas get updated along with primary nodes. This can be done, but it comes at a cost.



In practical world, DB will ensure that all nodes are updated before confirming to the client that operation is successful. In worst case, each node can take it's own sweet time to ensure that write/update is successful.

This can clearly mean that time, t1 >> t2 + t3 + t4

Host, might be unreachable for some time or it can go down. And unless, all nodes are updated; request will not be successful.

Your update is going to be slow and worst case really slow which will increase latency numbers and reduce throughput. Such system will not scale.  

Practical world is strongly consistent, but latency goes for a toss.
Practical world is not going to help us either!

Consistency in Distributed DBs

Quite obviously above approaches (which will bring strong consistency to system) is not practical, and it wont be exaggeration to say Impossible!. So, what option we have ?

We have only one option, store/update data on only one (primary/master) node and then update other nodes asynchronously.



Let's see how it's going to work when next request comes to read the data which is still undergoing replication to other nodes in asynchronous manner. In this case, system will behave depending on how the request gets handled. Below are possibilities:
  • Any node can return value. Now, if the primary node returns the value then it will be most recent but if a node which is yet to get the update will return stale or old value.  This is Week Consistency. This approach is used to achieve high availability. 
  • Only the primary node handles the request so you get the latest value. If DB can ensure that the data is returned from the primary node then client will get most recent value. This is Eventual Consistency. 

Saturday, March 11, 2017

Create Couchbase Cluster using Docker

This post walks you through steps to setup Couchbase cluster using Docker. Post expects that you already have Docker installed in your machine (Either of Linux, Mac or Windows)

Before starting the real work, make sure that Docker daemon is up and running.
$ sudo docker info
If daemon is NOT up; you will have something like below on your console:
Cannot connect to the Docker daemon. Is the docker daemon running on this host ?

If daemon is up, then you will have the details like Containers, OS, CPU, OS Name, docker root directory etc printed on the console.

To start Docker daemon (ref)
$ sudo service docker start

Run Couchbase as Dockerized Container

$ sudo docker run -d --name cb1 couchbase
On some of the platforms (like Mac) you need to specify the port mapping as well.
$ sudo docker run -d --name cb1 -p 8091-8094:8091-8094 -p 11210:11210 couchbase:enterprise-4.6.3

Above command runs Couchbase in detached mode (-d) and name is cb1.
$ sudo docker inspect cb1
Above command list all metadata of the cluster in JSON format. One of the important details to look for is IP address (with key IPAddress) of the couchbase server.

To launch couchbase in your browser use URL: http://<<ip_address>>:8091

Lanuch URL and then customize/configure couchbase server. To make it usable, you need to provide details like bucket, RAM, services which you want to run (if it supports multi dimensional scaling). Also, check the radio button 'Start a New Cluster' on CONFIGURE SERVER page.
This way, you will be able to successfully configure your first node.

Create Couchbase Cluster

Above step successfully launched one instance of Couchbase. To create a cluster you need to have minimum two instances of couchbase. 

Create another instance with a different name cb2. And then launch url as discussed in above step. But, be careful this time to Join a cluster (instead of start a new cluster). In the table, give your first instance IP address and then username and password.

Once, the new node is joined to the previous node your cluster is created. As, a final step go ahead and Rebalance your Couchbase to distribute data among nodes. 


---
happy learning !