Thursday, March 24, 2016

SSL enable Server and Client side code, KeyStore, KeyManagerFactory, SSLContext, SSLServerSocketFactory, easy example of Java SSL code, getting start with SSL, What is SSL, Wha is the use of SSL, keytool command, SSL Client java code, How to write SSL enable client side code


SSL (Secure Sockets Layer) provides a secure connection between internet browsers and websites, allowing you to transmit private data online. 

Server used to have private and public key (key OR certificate). Server creator either can take certificate from some well known Certificate Authority (CA) or generate their own certificate using java keytool command. When client wants to connect server, server send public key to client and handshake happens between both.

Using server's public key, all data which go from client to server are encrypted by server's public key and at server side using private key, server can decrypted those client data. But instead always using public and private key, after handshake both client and server use one symmetric key for their encryption and decryption.

How to generate your own key using JDK keytool command.
keytool -genkey -keystore demokeystore -keyalg RSA
I use "password" as password while generating this keystore.


SSLServerDemo.java

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;

public class SSLServerDemo {
    public static void main(String[] arstring) {
    SSLContext sslContext;
    System.out.println("** Servlet start with inbuild SSL **");
        try {
       
         InputStream kis = new FileInputStream("demokeystore");
         KeyStore keyStore = KeyStore.getInstance("jks");
         keyStore.load(kis, "password".toCharArray());
         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
         keyManagerFactory.init(keyStore, "password".toCharArray());
             
         sslContext = SSLContext.getInstance("TLS");
         sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
            
         SSLServerSocketFactory sslserversocketfactory = sslContext.getServerSocketFactory();
         SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(9000);
         SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

         InputStream inputstream = sslsocket.getInputStream();
         InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
         BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

         String string = null;
         while ((string = bufferedreader.readLine()) != null) {
                System.out.println("From SSL Server :"+string);
                System.out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


SSLClientDemo.java

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import java.io.*;
import java.security.KeyStore;

public class SSLClientDemo {
    public static void main(String[] arstring) {
    SSLContext sslContext;
        try {
       
          InputStream kis = new FileInputStream("demokeystore");
            KeyStore trustStore = KeyStore.getInstance("jks");
            trustStore.load(kis, "password".toCharArray());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);
                     
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            
             SSLSocketFactory sslsocketfactory = sslContext.getSocketFactory();
            SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 9000);

            InputStream inputstream = System.in;
            InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

            OutputStream outputstream = sslsocket.getOutputStream();
            OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream);
            BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);

            String string = null;
            while ((string = bufferedreader.readLine()) != null) {
                bufferedwriter.write(string + '\n');
                bufferedwriter.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Compile both java file and run both. Now if you type any message in client side, it will send to server side code.




Tuesday, March 22, 2016

How to write ElasticSearch 2.2 plugin, Getting start Elasticsearch Plugin, Develop ElasticSearch Plugin, How to debug elasticsearch plugin using eclipse, Remote debuging in Elasticsearch plugin, first plugin in Elasticsearch,


How to develop custom plugin for ElasticSearch 2.2

What is Plugin:
Plugins are a way to enhance the basic elasticsearch functionality in a custom manner. They range from adding custom mapping types, custom analyzers, native scripts, custom discovery and more.

There are three types of plugins:
- Java plugins
    These plugins contain only JAR files, and must be installed on every node in the cluster. After installation, each node must be restarted before the plugin becomes visible.
- Site plugins
    These plugins contain static web content like Javascript, HTML, and CSS files, that can be served directly from Elasticsearch.
    http://yournode:9200/_plugin/[plugin name]
- Mixed plugins
  Mixed plugins contain both JAR files and web content.

Here, I am going to develop Java Plugins.
1. Create one simple Maven project from Eclipse.
2. Add below things to your pom.xml
  
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.elasticsearch</groupId>
  <artifactId>es_plugin</artifactId>
  <version>1.1</version>
  <packaging>jar</packaging>

  <name>es_plugin</name>


  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

  <dependencies>
    <dependency>
             <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>2.2.1</version>
            <scope>provided</scope>
        </dependency>
     </dependencies>
   
     <build>
    <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.5.5</version>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <outputDirectory>${project.build.directory}/releases/</outputDirectory>
                    <descriptors>
                        <descriptor>${basedir}/src/main/assemblies/plugin.xml</descriptor>
                    </descriptors>
                </configuration>
                </plugin>
</plugins>
    </build>
 
</project>

   

3. In side src folder, you should have these three folders.
  src -> assemblies, java and resources subfolder
4. Inside assemblies folder, plugin.xml
5. Inside resources, plugin-descriptor.properties file should be there.
6. Inside java folder, all java file under package, In my case
   java\org\elasticsearch\es_plugin this folder has three java file.
   - App.java
   - ExampleRestModule.java
   - HelloRestHandler.java
 
** plugin.xml **

  <?xml version="1.0"?>
<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>plugin</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <useTransitiveFiltering>true</useTransitiveFiltering>
        </dependencySet>
    </dependencySets>
</assembly>


** plugin-descriptor.properties **

# All plugins, be they site or Java plugins, must contain a file called plugin-descriptor.properties in the root directory.
# Elasticsearch plugin descriptor file
description=Binod Suman ES Demo Plugin
version=1.1
# 'name': the plugin name
name=Binod ES Plugin Demo
jvm=true
# 'classname': the name of the class to load, fully-qualified.
#classname=com.netiq.scm.SCMPlugin
classname=org.elasticsearch.es_plugin.App
java.version=1.8
elasticsearch.version=2.2.1

** App.java **
package org.elasticsearch.es_plugin;

import java.util.Collection;
import java.util.Collections;

import org.elasticsearch.common.inject.Module;
import org.elasticsearch.plugins.Plugin;

@SuppressWarnings("static-method")
public class App extends Plugin {

    @Override
public String name() {
return "Binod Suman ElasticSearch Demo Name";
}

@Override
public String description() {
return "** Purpose for this plugin to how to write first ElasticSearch Demo";
}


@Override
    public Collection nodeModules() {
        return Collections.singletonList(new ExampleRestModule());
    }
}


** ExampleRestModule.java **
package org.elasticsearch.es_plugin;

import org.elasticsearch.common.inject.AbstractModule;

public class ExampleRestModule extends AbstractModule {

@Override
protected void configure() {
bind(HelloRestHandler.class).asEagerSingleton();
}

 }

 ** HelloRestHandler.java **
package org.elasticsearch.es_plugin;

import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;

public class HelloRestHandler extends AbstractComponent  {

@Inject
public HelloRestHandler(Settings settings) {
super(settings);
System.out.println("**** Hello I am here in HelloResthandler Module of ES 2 **");
}



}

** Now build your code by pom.xml **
mvn clean install
It will create one jar file "es_plugin.jar" inside target folder.

Create one folder in side your ElasticSearch installation Plugin folder. In my case, I created one folder
binod-demo-plugin inside E:\Software\elasticsearch-2.2.1\plugins folder.
Inside E:\Software\elasticsearch-2.2.1\plugins\binod-demo-plugin folder, I kept these two files:
 es_plugin.jar
 plugin-descriptor.properties

Now try to restart ElasticSearch.
E:\Software\elasticsearch-2.2.1\bin>elasticsearch.bat
[2016-03-22 23:03:38,140][INFO ][node                     ] [Bison] version[2.2.1], pid[13000], build[d045fc2/2016-03-09T09:38:54Z]
[2016-03-22 23:03:38,141][INFO ][node                     ] [Bison] initializing ...
[2016-03-22 23:03:38,689][INFO ][plugins                  ] [Bison] modules [lang-expression, lang-groovy], plugins [Binod ES Plugin Demo, scm], sites []
[2016-03-22 23:03:38,712][INFO ][env                      ] [Bison] using [1] data paths, mounts [[New Volume (E:)]], net usable_space [66.1gb], net total_space [157.8gb], spins? [unknown], types [NTFS]
[2016-03-22 23:03:38,712][INFO ][env                      ] [Bison] heap size [910.5mb], compressed ordinary object pointers [true]
[2016-03-22 23:03:38,931][INFO ][http                     ] [Bison] Using [org.elasticsearch.http.netty.NettyHttpServerTransport] as http transport, overridden by [SCM]
**** Hello I am here in HelloResthandler Module of ES 2 **
[2016-03-22 23:03:39,779][INFO ][com.netiq.scm.Util       ] [Bison] java.home = D:\InstalledFolder\Java\jdk1.8.0_45\jre
[2016-03-22 23:03:39,780][ERROR][com.netiq.scm.Util       ] [Bison] E:\Software\elasticsearch-2.2.1\config\db.properties (The system cannot find the file specified)
[2016-03-22 23:03:40,878][ERROR][com.netiq.scm.Util       ] [Bison] Cannot sync configuration from SCM Core. java.net.MalformedURLException: no protocol: nullconfig/[get]
[2016-03-22 23:03:40,997][INFO ][node                     ] [Bison] initialized
[2016-03-22 23:03:40,997][INFO ][node                     ] [Bison] starting ...
-03-22 23:03:47,695][INFO ][node                     ] [Bison] started

Here you can see the output carefully, some message comes from your own plugin.
 
**** How to set Debug breakpoint  *****
1. put break point of HelloRestHandler constructor
2. Add some extra parameter in elasticsearch.bat file.
   For More details: http://binodsuman.blogspot.in/2016/03/how-to-call-elasticsearch-in-debug-mode.html
3. Set one remote debug for this project in Eclipse.
4. Now start ElasticSearch.bat with extra debug parameter and start project in Eclipse.

 
 



How to call ElasticSearch in debug mode, ElasticSearch 2.2 starts in debug mode, active debug mode in ElasticSearch, bat file add debug mode parameter, How add debug in batch file, How to debug elasticsearch plugin using eclipse



Inside bat file, from where you are calling ElasticSearch (In my case E:\Software\elasticsearch-2.2.1\bin\elasticsearch.bat) add these parameter

-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8010

Then go to Eclipse and in Remote Debug put port 8010 for your ElasticSearch Plugin Code.

Here is full bat file to call ElasticSearch:

@echo off

SETLOCAL enabledelayedexpansion
TITLE Elasticsearch 2.2.1

SET params='%*'

:loop
FOR /F "usebackq tokens=1* delims= " %%A IN (!params!) DO (
    SET current=%%A
    SET params='%%B'
SET silent=N

IF "!current!" == "-s" (
SET silent=Y
)
IF "!current!" == "--silent" (
SET silent=Y
)

IF "!silent!" == "Y" (
SET nopauseonerror=Y
) ELSE (
   IF "x!newparams!" NEQ "x" (
       SET newparams=!newparams! !current!
        ) ELSE (
            SET newparams=!current!
        )
)

    IF "x!params!" NEQ "x" (
GOTO loop
)
)

SET HOSTNAME=%COMPUTERNAME%

CALL "%~dp0elasticsearch.in.bat"
IF ERRORLEVEL 1 (
IF NOT DEFINED nopauseonerror (
PAUSE
)
EXIT /B %ERRORLEVEL%
)

"%JAVA_HOME%\bin\java"  -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8010 %JAVA_OPTS% %ES_JAVA_OPTS% %ES_PARAMS% -cp "%ES_CLASSPATH%" "org.elasticsearch.bootstrap.Elasticsearch" start !newparams!

ENDLOCAL

Wednesday, March 2, 2016

Java Regex to Validate IPV4, IPV6 IP address and Port range, Java IP address validation, Regex expression for IP address



private static final String ipv4Pattern = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])";
private static final String ipv6Patten = "^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}"
            + "|([0-9A-F]{1,4}:){6})(\\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]"
            + "|(2[0-4]|1\\d|[1-9])?\\d)(\\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,"
            + "4})(?<![^:]:|\\.)\\z";

    private static final String portRegex = "^(6553[0-5]|655[0-2]\\d|65[0-4]\\d\\d|6[0-4]\\d{3}|[1-5]\\d{4}|[2-9]\\d{3}|1[1-9]\\d{2}|10[3-9]\\d|102[4-9])$";


Complete Code:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;


public class IPValidate {
private static Pattern VALID_IPV4_PATTERN = null;
private static Pattern VALID_IPV6_PATTERN = null;
private static Pattern VALID_PORT_PATTERN = null;
private static Pattern CHECK_IPV6_ADDRESS = null;
private static String COMMA = ",";
private static String COLON = ":";
private static String CLOSE_BRACKET = "]";
private static String CLOSE_BRACKET_AND_COLON = "]:";
private static final String ipv4Pattern = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])";
private static final String ipv6Patten = "^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}"
            + "|([0-9A-F]{1,4}:){6})(\\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]"
            + "|(2[0-4]|1\\d|[1-9])?\\d)(\\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,"
            + "4})(?<![^:]:|\\.)\\z";
    private static final String portRegex = "^(6553[0-5]|655[0-2]\\d|65[0-4]\\d\\d|6[0-4]\\d{3}|[1-5]\\d{4}|[2-9]\\d{3}|1[1-9]\\d{2}|10[3-9]\\d|102[4-9])$";
private static final String ip6address = "^\\[([0-9a-fA-F:]*)\\]:(.*)";
public IPValidate(){
VALID_IPV4_PATTERN = Pattern.compile(ipv4Pattern, Pattern.CASE_INSENSITIVE);
VALID_IPV6_PATTERN = Pattern.compile(ipv6Patten, Pattern.CASE_INSENSITIVE);
VALID_PORT_PATTERN = Pattern.compile(portRegex, Pattern.CASE_INSENSITIVE);
CHECK_IPV6_ADDRESS = Pattern.compile(ip6address, Pattern.CASE_INSENSITIVE);
}
private boolean validateIP4Address(String ip){
return VALID_IPV4_PATTERN.matcher(ip).matches();
}
private boolean validateIP6Address(String ip){
return VALID_IPV6_PATTERN.matcher(ip).matches();
}
private boolean validatePortNumber(String port){
return VALID_PORT_PATTERN.matcher(port).matches();
}
private boolean isIPV6Address(String ip){
return ip.contains("[")&&ip.contains("]");
}
private List getSeperatedList(String data, String delimeter){
//return Pattern.compile(delimeter).splitAsStream(data).collect(Collectors.toList());
return new ArrayList(Arrays.asList(data.split(delimeter)));
}

public boolean validateIPAddress(String ips){
List ipsList = getSeperatedList(ips,COMMA);
List ipAndPort = null;
String ipAddress = null;
String port = null;
for(String ip : ipsList){
ip=ip.trim();
if(isIPV6Address(ip)){
ipAndPort = getSeperatedList(ip,CLOSE_BRACKET_AND_COLON);
if(ipAndPort.size()!=2){
System.out.println("Invalid format. Please specify the IP addresses and port numbers again."); 
return false;
}
ipAddress = ipAndPort.get(0).trim().substring(1); // to remove [
port = ipAndPort.get(1).trim(); // to remove :
if(!(validateIP6Address(ipAddress))){
System.out.println("The specified IVP6 address is invalid. Please specify the IP addresses again.");
return false;
}
}else{
ipAndPort = getSeperatedList(ip,COLON);
if(ipAndPort.size()!=2){
System.out.println("Invalid format. Please specify the IP addresses and port numbers again.");
return false;
}
ipAddress = ipAndPort.get(0).trim();
port = ipAndPort.get(1).trim();
if(!(validateIP4Address(ipAddress))){
System.out.println("The specified IPV4 address is invalid. Please specify the IP addresses again.");
return false;
}
}
if(!(validatePortNumber(port))){
System.out.println("The specified port is invalid. Please specify port numbers again.");
return false;
}
}
return true;
}
public static void main(String[] args) {
IPValidate demo = new IPValidate();
String ips = "[2001:0:1234::c1c0:abcd:876d]:9090,10.90.200.252:6500,29.90.39.89:2918,[2001:0:1234::c1c0:abcd:876]:9090";
//String ips = "[::1]:9090,10.90.20.98:8009";
//String ips = "[::1]:9099";
//String ips = "2.3.4.5:3757";
//String ips="";
boolean isIPAddressValidate = demo.validateIPAddress(ips);
System.out.println("isIPAddressValidate :"+isIPAddressValidate);
}

}