Tuesday 31 October 2017

mod_proxy || mod_jk || mod_cluster


mod_proxy

This proxy can either use HTTP or AJP for routing request from Apache to JBoss. The advantage of mod_proxy is that it is available as a built in module in Apache 2.x versions.

Advantage:
  •          No need to compile and maintain an opposite module. Mod_proxy, mod_proxy_http, mod_proxy_ajp, mod_proxy_balancer is Apache 2.2+ standard integrated part,
  •          You can use the HTTP, HTTPS and AJP protocols, even in the same balancer.
Inferiority:
  •          Mod_proxy_ajp does not support more than 8K data packet,
  •          Only the most basic load balancer,
  •          Does not support domain model cluster(domain model clustering)

mod_jk

Mod_jk is based on the AJP protocol, mod_jk connector is an Apache module specifically written by Tomcat team. This module routes the Apache to JBoss request via the AJP (Apache Jserv Protocol).

Advantage:
  •  The load balancer advanced,
  •   Advanced node failure detection function,
  •   Support for large-scale AJP packet
Inferiority:
  •          The need for a separate maintenance of an independent module,

mod_cluster

mod_cluster is an httpd-based load balancer. Like mod_jk and mod_proxy, mod_cluster uses a communication channel to forward requests from httpd to one of a set of application server nodes. Unlike mod_jk and mod_proxy, mod_cluster leverages an additional connection between the application server nodes and httpd. The application server nodes use this connection to transmit server-side load balance factors and lifecycle events back to httpd via a custom set of HTTP methods, affectionately called the Mod-Cluster Management Protocol (MCMP). This additional feedback channel allows mod_cluster to offer a level of intelligence and granularity not found in other load balancing solutions.

Advantages:

  •          Dynamic configuration of httpd workers
Traditional httpd-based load balancers require explicit configuration of the workers available to a proxy. In mod_cluster, the bulk of the proxy's configuration resides on the application servers. The set of proxies to which an application server will communicate is determined either by a static list or using dynamic discovery via the advertise mechanism. The application server relays lifecycle events (e.g. server startup/shutdown) to the proxies allowing them to effectively auto-configure themselves. Notably, the graceful shutdown of a server will not result in a failover response by a proxy, as is the case with traditional httpd-based load balancers.
  •          Server-side load balance factor calculation
In contrast with traditional httpd-based load balancers, mod_cluster uses load balance factors calculated and provided by the application servers, rather than computing these in the proxy. Consequently, mod_cluster offers a more robust and accurate set of load metrics than is available from the proxy. (see Load Metrics for more)
  •          Fine grained web-app lifecycle control
Traditional httpd-based load balancers do not handle web application undeployments particularly well. From the proxy's perspective requests to an undeployed web application are indistinguishable from a request for an non-existent resource, and will result in 404 errors. In mod_cluster, each server forwards any web application context lifecycle events (e.g. web-app deploy/undeploy) to the proxy informing it to start/stop routing requests for a given context to that server.
  • AJP is optional
Unlike mod_jk, mod_cluster does not require AJP. httpd connections to application server nodes can use HTTP, HTTPS, or AJP.

Tuesday 24 October 2017

Monitor DataSource connection pool statistics in JBoss EAP

In this post we focus on DataSource connection pool statistics for your application with
The Command Line Interface (CLI).

In EAP 6.3 and later, DataSource statistics need to be explicitly enabled as they are disabled by default to minimize performance impact.

By using below command you can enable DataSource connection pool statistics. after that restart the servers to take effect.

Syntax: /profile=<Profilename>/subsystem=datasources/data-source=< data-source Name>:write-attribute (name=statistics-enabled,value=true)

[domain@192.168.1.12:9999 /] /profile=better/subsystem=datasources/data-source=BetterDS:write-attribute(name=statistics-enabled, value=true)
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}


Then check the DataSource statistics:

To view the statistics via management console, migrate to the Runtime Tab. Go to Subsystems --> Datasources. Click on the data-source whose statistics you need to view.

CLI example in Domain mode:

Core Statistics :

Syntax: host=<HC name>/server=<AS name>/subsystem=datasources/data-data=<data source name>/statistics=pool:read-resource(recursive=true, include-runtime=true)

[domain@192.168.1.12:9999 /]/host=slave01/server=better-as1/subsystem=datasources/data-source=BetterDS/statistics=pool:read-resource(recursive=true, include-runtime=true)
{
    "outcome" => "success",
    "result" => {
        "ActiveCount" => "1",
        "AvailableCount" => "20",
        "AverageBlockingTime" => "0",
        "AverageCreationTime" => "2583",
        "CreatedCount" => "2",
        "DestroyedCount" => "1",
        "InUseCount" => "0",
        "MaxCreationTime" => "5092",
        "MaxUsedCount" => "1",
        "MaxWaitCount" => "0",
        "MaxWaitTime" => "0",
        "TimedOut" => "1",
        "TotalBlockingTime" => "0",
        "TotalCreationTime" => "5166",
        "statistics-enabled" => true
    }
}

 The following table contains a list of the supported datasource core statistics:

Name
Description
ActiveCount
The number of active connections. Each of the connections is either in use by an application or available in the pool
AvailableCount
The number of available connections in the pool.
AverageBlockingTime
The average time spent blocking on obtaining an exclusive lock on the pool. The value is in milliseconds.
AverageCreationTime
The average time spent creating a connection. The value is in milliseconds.
CreatedCount
The number of connections created.
DestroyedCount
The number of connections destroyed.
InUseCount
The number of connections currently in use.
MaxCreationTime
The maximum time it took to create a connection. The value is in milliseconds.
MaxUsedCount
The maximum number of connections used.
MaxWaitCount
The maximum number of requests waiting for a connection at the same time.
MaxWaitTime
The maximum time spent waiting for an exclusive lock on the pool.
TimedOut
The number of timed out connections.
TotalBlockingTime
The total time spent waiting for an exclusive lock on the pool. The value is in milliseconds.
TotalCreationTime
The total time spent creating connections. The value is in milliseconds.
WaitCount
The number of requests that had to wait for a connection.

JDBC Statistics

Syntax: host=<HC name>/server=<AS name>/subsystem=datasources/data-data=<data source name>/statistics=jdbc:read-resource(recursive=true, include-runtime=true)

[domain@192.168.1.12:9999 /]/host=slave01/server=better-as1/subsystem=datasources/data-source=BetterDS/statistics=jdbc:read-resource(recursive=true, include-runtime=true)
{
    "outcome" => "success",
    "result" => {
        "PreparedStatementCacheAccessCount" => "0",
        "PreparedStatementCacheAddCount" => "0",
        "PreparedStatementCacheCurrentSize" => "0",
        "PreparedStatementCacheDeleteCount" => "0",
        "PreparedStatementCacheHitCount" => "0",
        "PreparedStatementCacheMissCount" => "0",
        "statistics-enabled" => true
    }

}



The following table contains a list of the supported datasource JDBC statistics:


Name
Description
PreparedStatementCacheAccessCount
The number of times that the statement cache was accessed.
PreparedStatementCacheAddCount
The number of statements added to the statement cache.
PreparedStatementCacheCurrentSize
The number of prepared and callable statements currently cached in the statement cache.
PreparedStatementCacheDeleteCount
The number of statements discarded from the cache.
PreparedStatementCacheHitCount
The number of times that statements from the cache were used.
PreparedStatementCacheMissCount
The number of times that a statement request could not be satisfied with a statement from the cache.



please subscribe my blog  and provide the feedback on this article/blog to improve the articles.

Monday 23 October 2017

DataSource passwords Decryption in JBOSS EAP 6/7

JBoss Uses Pretty Simple process to encrypt and decrypt plain text Strings to encrypt. The encryption is provided by JBoss. The code for encryption and decryption are as below. 


import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class DecodeIdentity {
   
   private static String encode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,InvalidKeyException, BadPaddingException, IllegalBlockSizeException{
      byte[] kbytes = "jaas is the way".getBytes();
      SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");
      Cipher cipher = Cipher.getInstance("Blowfish");
      cipher.init(Cipher.ENCRYPT_MODE, key);
      byte[] encoding = cipher.doFinal(secret.getBytes());
      BigInteger n = new BigInteger(encoding);
      return n.toString(16);
   }

   private static char[] decode(String secret)throws NoSuchPaddingException, NoSuchAlgorithmException,InvalidKeyException, BadPaddingException, IllegalBlockSizeException{
      byte[] kbytes = "jaas is the way".getBytes();
      SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");
      BigInteger n = new BigInteger(secret, 16);
      byte[] encoding = n.toByteArray();
      //SECURITY-344: fix leading zeros
      if (encoding.length % 8 != 0){
         int length = encoding.length;
         int newLength = ((length / 8) + 1) * 8;
         int pad = newLength - length; //number of leading zeros
         byte[] old = encoding;
         encoding = new byte[newLength];
         for (int i = old.length - 1; i >= 0; i--){
            encoding[i + pad] = old[i];
         }
         if (n.signum() == -1){
            for (int i = 0; i < newLength - length; i++){
               encoding[i] = (byte) -1;
            }
         }
      }
      Cipher cipher = Cipher.getInstance("Blowfish");
      cipher.init(Cipher.DECRYPT_MODE, key);
      byte[] decode = cipher.doFinal(encoding);
      return new String(decode).toCharArray();
   }
   public static void main(String[] args) throws Exception{
      if(args.length == 2){
          if (args[0].equals("encode")){
            String encode = encode(args[1]);
            System.out.println("Encoded password: " + encode);
          }else if (args[0].equals("decode")){
            System.out.println(decode(args[1])); 
          }else{
              System.out.println("Function not defined");
          }
      }
   }
}



Copy the above Code and create a file DecodeIdentity.java and place the file in home Directory:

Let see how this java code will work:




please subscribe my blog  and provide the feedback on this article/blog to improve the articles.

Saturday 21 October 2017

How to use encrypted passwords in EAP6/7 Datasources

It’s always a risk if you are storing plain-text passwords on the file system. A good system administrating practice is to make sure that passwords are always stored in encrypted form. By default JBoss EAP6 data source passwords are stored in plaintext inside standalone.xml/domain.xml. JBoss EAP6 uses picketbox security implementation for encrypting data source passwords.

In this post we will see step-by-step process to Encrypt Data Source Passwords in JBoss EAP6 or 7.

Download the following script and store it in a location such as /JBOSS_HOME/bin. Provide the file permissions and ownership for this script as you see fit. In this example, they are:

#!/bin/sh
# Script Name :  Datasource-password.sh
############################################################
#Make your changes here only  

export JAVA_HOME="/usr/java/jdk1.8.0_121"
export PATH=/usr/java/jdk1.8.0_121/bin:$PATH
JBOSS_HOME="/u02/jboss/jboss-eap-7.0"
OVERLAY_DIRECTORY="$JBOSS_HOME/modules/system/layers/base/.overlays"

#############################################################
echo ""
read -p "Please enter the password to be encrypted : " PASSWORD
echo ""

if [ -d "$OVERLAY_DIRECTORY" ]; then
    PATCH_SUBDIRECTORY=$(ls -dt $OVERLAY_DIRECTORY/* | grep "CP" | head -n 1)   
    echo patch subdirectory is: "$PATCH_SUBDIRECTORY"
    SEARCH_DIRECTORY="$PATCH_SUBDIRECTORY/org/picketbox/main"
else
    SEARCH_DIRECTORY="$JBOSS_HOME/modules/system/layers/base/org/picketbox/main"
fi

export CLASSPATH=$(find $(cd "$SEARCH_DIRECTORY"; pwd) -name "*.jar" -print | tr '\n' ':')$CLASSPATH

echo -e "\x1b[31m----------------------------------------------------\033[0m\e[0m"
java org.picketbox.datasource.security.SecureIdentityLoginModule "$PASSWORD"
echo -e "\x1b[31m----------------------------------------------------\033[0m\e[0m"
echo ""

1.   Encrypt the database password by running the above script:











Now we have encrypted database password.  


2.      In your JBoss configuration file i.e. standalone.xml or domain.xml create a security-domain in the security subsystem, specifying the encrypted database password 

  <security-domain name="encryptedSecurityDomain" cache-type="default">
                    <authentication>
                        <login-module code="org.picketbox.datasource.security.SecureIdentityLoginModule" flag="required">
                            <module-option name="username" value="dbUserName"/>
                            <module-option name="password" value="4e74076d773dcbe48f534e004d35e2de"/>
                        </login-module>
                    </authentication>
                </security-domain>

The above can be done via the following CLI commands in standalone server (for domain mode add /profile=<Profile-Name> to the beginning of each command):

/subsystem=security/security-domain=encryptedSecurityDomain:add(cache-type=default)

/subsystem=security/security-domain=encryptedSecurityDomain/authentication=classic:add

/subsystem=security/security-domain=encryptedSecurityDomain/authentication=classic/login-module="encryptedSecurityDomain-Module":add(code="org.picketbox.datasource.security.SecureIdentityLoginModule",flag=required, module-options={"username" => "dbUserName", "password" => "4e74076d773dcbe48f534e004d35e2de"})

3.   Define the security domain in DataSource configuration. 

Stop the respective application servers and disable the Datasource and add the security domain as below and remove the username and password:























The above can be done via the following CLI commands  

Disable the data-source

[domain@192.168.1.12:9999 /] /profile=better/subsystem=datasources/data-source=BetterDS:disable
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}

Undefined  the password attribute

[domain@192.168.1.12:9999 /] /profile=better/subsystem=datasources/data-source=BetterDS:undefine-attribute(name=password)
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}

Undefined  the user-name attribute

[domain@192.168.1.12:9999 /] /profile=better/subsystem=datasources/data-source=BetterDS:undefine-attribute(name=user-name)
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}


Add the security-domain attribute to DataSource

[domain@192.168.1.12:9999 /] /profile=better/subsystem=datasources/data-source=BetterDS:write-attribute(name=security-domain, value=encryptedSecurityDomain)
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}

Enable the DataSource :

[domain@192.168.1.12:9999 /] /profile=better/subsystem=datasources/data-source=BetterDS:enable
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}
[domain@192.168.1.12:9999 /]

4. Start the application servers and check test connection for the DataSource:

[domain@192.168.1.12:9999 /] /host=slave01/server=better-as1/subsystem=datasources/data-source=BetterDS:test-connection-in-pool()
{
    "outcome" => "success",
    "result" => [true]
}

IF your configuration is correct, you should see the below output in JBoss logs which indicates that the Data Source was registered without any issues

02:55:21,486 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-1) JBAS010400: Bound data source [java:/BetterDS]

Additional Information
For 2 different Datasources configured in the same profile, create separate security-domain with respective username and encrypted password.


5.   DataSource credentials update in Security domain : 

If you want to change Databse credentials in Security domain, First get the Encoded_password of DB password with above script and run/use below CLI command
  
Syntax :  /profile=<Profile-Name>/subsystem=security/security-domain=encryptedSecurityDomain/authentication=classic/login-module=encryptedSecurityDomain-Module:write-attribute(name=module-options, value={"username" => "<DB-User>", "password" => "<Encoded_password>"})

Example : 
[domain@192.168.1.12:9999 /] /profile=better/subsystem=security/security-domain=encryptedSecurityDomain/authentication=classic/login-module=encryptedSecurityDomain-Module:write-attribute(name=module-options, value={"username" => "BetterDB1", "password" => "6127123fdd287b2d872fda70df0c80b9"})
{
    "outcome" => "success",
    "result" => undefined,
    "server-groups" => undefined
}