Thursday 10 December 2015

Tomcat host based whitelisting

This is how to white list based on host names in tomcat.
you need to use RemoteHostValve in server.xml in the HOST container.
below is how it looks:


<Valve className="org.apache.catalina.valves.RemoteHostValve"
                    deny="^(?!(sherif\.tot\.corp\.com|ashraf\.co\.corp\.com|.*\.help\.corp\.com|.*\.corp\.com)).*$"
                    />

for this to work correclty, you need to enable lookups in the Tomcat connectors:

 <Connector acceptCount="100"
                   URIEncoding="UTF-8"
                   connectionTimeout="20000"
                   executor="tomcatThreadPool"
                   maxKeepAliveRequests="15"
                   port="${bio.http.port}"
                   enableLookups="true"
                   protocol="org.apache.coyote.http11.Http11Protocol"
                   redirectPort="${bio.https.port}"/>

The above will allow hosts mentioned to access the tomcat, any other hosts will be denied.
Wild cards are allowed as in the last 2 entried.
Oring happens using "|" (pipes) and the RegEx is java RegEx so take care since it is not same as standard Unix RegEx.

Saturday 22 August 2015

Using gnuplot for trend analysis

I was looking for a simple tool to draw trend info for data collected from my servers, i have been using cacti effectively and it is serving me quite well, still i need to be able to run some ad-hoc graphs from time to to time.
I came across gnuplot and didn't consider using it, but now, i found those 3 great resources that will change my apporache:

http://linux.byexamples.com/archives/487/plot-your-graphs-with-command-line-gnuplot/

http://people.duke.edu/~hpgavin/gnuplot.html

Those 2 articles made it very easy for me to understand the tool and be able to use its demos at:

http://gnuplot.sourceforge.net/demo_4.6/


below is my test script:

test.data:

#month reading consumption
1   700          830
2   1120         1125
3   1400         1400
4   1790         1750
5   2100         2150
6   2450         2455
7   2900         2910
8   3210         3230
9   3300         3350
10  3780         3785
11  4090         4110
12  4550         4640
13  4550         4950
14  4550         5350









test.gp:

reset
set terminal png


#set xdata time
#set timefmt "%d/%m/%Y %H:%M:%S"
#set format x "%H:%M"
set xlabel "Month #"

set ylabel "Monthly Reading"
#set yrange [0:31]

set title "M7YC Performance per Month"
#set key reverse Left outside
set key bottom center outside
#set key bottom horizontal center outside
set grid

#set style data linespoints
#set style data impulses
#set style data boxes
set style data histogram
set style histogram cluster gap 2
set style fill solid border 0
set boxwidth 1


#Plot with different patterns in one command
#plot "./test.data" using 1:2 title "Monthly Reading" with linespoints, \
#"" using 1:3 title "Actual consumption" with boxes

#Plot with style setting
#plot "./test.data" using 1:2 title "Monthly Reading" , \
#"" using 1:3 title "Actual consumption"



#Plot a histo
plot "./test.data" using 2 title "Monthly Reading" , \
"" using 3 title "Actual consumption"


#




The above have a lot of potential to generate png graphs that can be embeded in HTML pages and serve as needed.
Also we can customize the graphs and use shell scripting to tune and manipulate the script and the data dynamically.

will explore more about this and post the works . .




Reporting JMX attributes from Tomcat using command line

We have run into an issue with number of tomcat active sessions that was causing us a memory bottleneck while doing performance testing.
So to track this we did a heap dump and a set of heap histograms to see what is the size of the Session object and current number of open sessions.
We managed to find the issue with the test scenario but, we found out that doing a heap histo would pause the JVM for a second or 2 which added to our performance issues.

So we need another command line way to report sessions.
Java does provide jconsole and JvisualVM with Mbean plugins but both tools are GUI tools not suitable for reporting from command line and automation.
We needed some way to automate this for doing a report across 9 nodes.

I have found some good command line tools but some of them are out of date and others are too complex for the job or requires an externally exposed JMX which is not allowed by our org. security.

So i needed to look for some java code to do this trick for me, i found out an oracle blog example code that would report JVM arguments, classpath, start time from JMX at the below link:

https://blogs.oracle.com/jmxetc/entry/how_to_retrieve_remote_jvm


The good thing about this code is it uses the Java tools to attache to the JVM locally so i didn't have to expose JVM externally which is forbidden by our security team.

One issue i faced it that i didn't know how to report the active sessions out of tomcat, so I asked my friend Bassem Zohdy who created a demo for me doing the needed functionality:

https://github.com/bassemZohdy/tomcatActiveSessionLocalJMXDemo


What i did is I updated the Oracle blog example code with what Bassem did and i got a cool running commandline tool that can report active sessions.
below is the java code:


                                                  

//package jvmruntime;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;                
import java.util.logging.Logger;            
import javax.management.remote.JMXServiceURL;
import com.sun.tools.attach.VirtualMachine; 
import com.sun.tools.attach.VirtualMachineDescriptor;
import java.lang.management.RuntimeMXBean;         
import java.util.ArrayList;                        
import java.util.List;                             
import javax.management.MBeanServerConnection;     
import javax.management.remote.JMXConnector;       
import javax.management.remote.JMXConnectorFactory;
import javax.management.ObjectName;                

public class JVMRuntimeClient {
                             
    private static final Logger LOG =
            Logger.getLogger(JVMRuntimeClient.class.getName());
                                                             
    public JVMRuntimeClient() {                              
    }                                                        

    public static class ConnectionArgs {
        private static final String CONNECTOR_ADDRESS =
          "com.sun.management.jmxremote.localConnectorAddress";
                                                             
                                                             
        public final JMXServiceURL jmxURL;                   
        final public String SYNTAX = "JVMRuntimeClient -url <jmx-url> " +
                "| -port <port-number> [-host <host-or-ip] " +         
                "| -pid <pid> | -help";                                
                                                                       
        public ConnectionArgs(String[] args) {                         
            jmxURL = parseArgs(args);                                  
        }                                                              
                                                                       
        public final JMXServiceURL getJMXServiceURL() {                
            return jmxURL;                                             
        }                                                              
                                                                       
        private JMXServiceURL parseArgs(String[] args) {               
                                                                       
            String host = null;                                        
            int port = 0;                                              
            String pid = null;                                         
            JMXServiceURL serviceURL = null;                           
                                                                       
            for (int i=0;i<args.length;i++) {                          
                                                                       
                if (args[i].startsWith("-url")) {                      
                // The '-url' option will let you specify a JMXServiceURL
                // on the command line. This is an URL that begins with
                // service:jmx:<protocol>                              
                //                                                     
                    if (host != null)                                  
                        throwSyntaxError(                              
                                "-url and -host are mutually exclusive");
                    if (pid != null)                                   
                        throwSyntaxError(                              
                                "-pid and -url are mutually exclusive");
                    if (port > 0)                                      
                        throwSyntaxError(                              
                                "-port and -url are mutually exclusive");
                    if (++i >= args.length)                            
                        throwSyntaxError(                              
                                "missing JMXServiceURL after -url");   
                                                                       
                    try {                                              
                        serviceURL = new JMXServiceURL(args[i]);       
                    } catch (Exception x) {                            
                        throwSyntaxError("bad JMXServiceURL after -url: " + x);
                    }                                                        
                    continue;                                                
                                                                             
                } else if (args[i].startsWith("-host")) {                    
                // The '-host' and '-port' options will let you specify a host
                // and port, and from that will construct the JMXServiceURL of
                // the default RMI connector, that is:                       
                // service:jmx:rmi:///jndi/rmi://<host>:<port>/jmxrmi"       
                //                                                           
                    if (serviceURL != null)                                  
                        throwSyntaxError("-url and -host are mutually exclusive");
                    if (pid != null)                                            
                        throwSyntaxError("-pid and -host are mutually exclusive");
                    if (++i >= args.length)                                     
                        throwSyntaxError("missing host after -host");           
                    try {                                                       
                        InetAddress.getByName(args[i]);                         
                        host = args[i];                                         
                    } catch (Exception x) {                                     
                        throwSyntaxError("bad host after -url: " + x);          
                    }                                                           
                                                                                
                } else if (args[i].startsWith("-port")) {                       
                // The '-host' and '-port' options will let you specify a host  
                // and port, and from that will construct the JMXServiceURL of  
                // the default RMI connector, that is:                          
                // service:jmx:rmi:///jndi/rmi://<host>:<port>/jmxrmi"          
                //                                                              
                    if (serviceURL != null)                                     
                        throwSyntaxError("-url and -port are mutually exclusive");
                    if (pid != null)                                            
                        throwSyntaxError("-pid and -port are mutually exclusive");
                    if (++i >= args.length)                                     
                        throwSyntaxError("missing port number after -port");    
                    try {                                                       
                        port = Integer.parseInt(args[i]);                       
                        if (port <= 0)                                          
                            throwSyntaxError("bad port number after -port: " +  
                                    "must be positive");                        
                    } catch (Exception x) {                                     
                        throwSyntaxError("bad port number after -port: " + x);  
                    }                                                           
                } else if (args[i].startsWith("-pid")) {                        
                // The '-pid' and option will let you specify the PID of the    
                // target VM you want to connect to. It will then use the       
                // attach API to dynamically launch the JMX agent in the target 
                // VM (if needed) and to find out the JMXServiceURL of the      
                // the default JMX Connector in that VM.                        
                //                                                              
                    if (serviceURL != null)                                     
                        throwSyntaxError("-url and -pid are mutually exclusive");
                    if (port > 0)                                               
                        throwSyntaxError("-port and -pid are mutually exclusive");
                    if (++i >= args.length)                                     
                        throwSyntaxError("missing pid after -pid");             
                    try {                                                       
                        pid = args[i];                                          
                    } catch (Exception x) {                                     
                        throwSyntaxError("bad pid after -pid: " + x);           
                    }                                                           
                } else if (args[i].startsWith("-help")) {                       
                    final List<String> vmlist = new ArrayList();                
                    for (VirtualMachineDescriptor vd : VirtualMachine.list()) { 
                        vmlist.add(vd.id());                                    
                    }                                                           
                    System.err.println(SYNTAX);                                 
                    System.err.println("Running JVMs are: "+vmlist);            
                    throw new IllegalArgumentException(SYNTAX);                 
                } else {                                                        
                    throwSyntaxError("Unknown argument: "+args[i]);             
                }                                                               
            }                                                                                                                                                      
            // A JMXServiceURL was given on the command line, just use this.    
            //                                                                  
            if (serviceURL != null)                                             
                return serviceURL;                                                           // A -host -port info was given on the command line.                
            // Construct the default RMI JMXServiceURL from this.               
            //                                                                  
            if (port > 0) {                                                     
                if (host == null)                                               
                    host = "localhost";                                           
                try {                                                           
                    return new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+  
                            host+":"+port+"/jmxrmi");                           
                } catch (Exception x) {                                         
                    throwSyntaxError("Bad host or port number: "+x);            
                }                                                               
            }                                                                   
                                                                                
            // A PID was given on the command line.                             
            // Use the attach API to find the target's connector address, and   
            // start it if needed.                                              
            //                                                                  
            if (pid != null) {                                                  
                try {                                                           
                    return getURLForPid(pid);                                   
                } catch (Exception x) {                                         
                    throwSyntaxError("cannot attach to target vm "+pid+": "+x); 
                }                                                               
            }                                                                   
                                                                                
            final List<String> vmlist = new ArrayList();                        
            for (VirtualMachineDescriptor vd : VirtualMachine.list()) {         
                vmlist.add(vd.id());                                            
            }                                                                   
            throwSyntaxError("missing argument: "+ "-port | -url | -pid | -list"
                    +"\\n\\tRunning VMs are: "+vmlist);                         
                                                                                
            // Unreachable.                                                     
            return null;                                                        
        }                                                                       
                                                                                
                                                                                
        private void throwSyntaxError(String msg) {                             
            System.err.println(msg);                                            
            System.err.println(SYNTAX);                                         
            throw new IllegalArgumentException(msg);                            
        }                                                                       

        private JMXServiceURL getURLForPid(String pid) throws Exception {
                                                                       
            // attach to the target application                        
            final VirtualMachine vm = VirtualMachine.attach(pid);      
                                                                       
            // get the connector address                               
            String connectorAddress =                                  
                    vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
                                                                         
            // no connector address, so we start the JMX agent           
            if (connectorAddress == null) {                              
                String agent = vm.getSystemProperties().getProperty("java.home") +
                        File.separator + "lib" + File.separator + "management-agent.jar";
                vm.loadAgent(agent);                                                   
                                                                                       
                // agent is started, get the connector address                         
                connectorAddress =                                                     
                        vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);        
                assert connectorAddress != null;                                       
            }                                                                          
            return new JMXServiceURL(connectorAddress);                                
        }                                                                              
    }                                                                                  
                                                                                       
     // @param args the command line arguments:                                        
     //             must be -url <jmx-url>,                                            
     //             or -port <port-number> [-host <host-or-ip],                        
     //             or -pid <pid>,                                                     
     //             or -help                                                           
     //                                                                                
    public static void main(String[] args) throws Exception {                          
        // Parse arguments.
        final ConnectionArgs cArgs = new ConnectionArgs(args);

        // Get target's URL
        final JMXServiceURL target = cArgs.getJMXServiceURL();

        // Connect to target (assuming no security)
        final JMXConnector connector = JMXConnectorFactory.connect(target);

        // Get an MBeanServerConnection on the remote VM.
        final MBeanServerConnection remote =
                connector.getMBeanServerConnection();

        final RuntimeMXBean remoteRuntime =
                ManagementFactory.newPlatformMXBeanProxy(
                    remote,
                    ManagementFactory.RUNTIME_MXBEAN_NAME,
                    RuntimeMXBean.class);

        //Bassem's code
        final ObjectName objectName = new ObjectName(
                                "Catalina:type=Manager,host=localhost,context="+"/");

        System.out.println("ActiveSession = "
                                + remote.getAttribute(objectName, "activeSessions"));
        //END of Bassem's code

        //System.out.println("Target VM is: "+remoteRuntime.getName());
        //System.out.println("Started since: "+remoteRuntime.getUptime());
        //System.out.println("With Classpath: "+remoteRuntime.getClassPath());
        //System.out.println("And args: "+remoteRuntime.getInputArguments());


        connector.close();
    }

}



To compile and run this code you need to do:

javac -classpath /usr/java/jdk1.8.0_25/lib/tools.jar: ./JVMRuntimeClient.java

java -classpath /usr/java/jdk1.8.0_25/lib/tools.jar: JVMRuntimeClient -pid 3689



Thursday 6 August 2015

Wget Recrusively with password encryption

This is a good script to download folders from a website.
Tweek the cut dirs to suit ur needs

[root]# cat svnget.sh

MyPASS=$(echo "ULLLjhsPpssjFGsmyMVpwtLwhdjdhjdhjLLDLDi9e##nsBBPPs=" |openssl enc -desx -base64 -d)

wget --user=sherif--password=${MyPASS} \
-e robots=off --cut-dirs=4 \
-nH \
--reject="index.html*"  --no-parent \
--recursive  $1

MyPASS=0
[root]#

Wednesday 22 July 2015

Password encryption in a shell script

This is a good article on how to encrypt a password on Linux for use in a shell script:

http://how-to.linuxcareer.com/using-openssl-to-encrypt-messages-and-files

the bottom line is to use the following command:

echo "some password"  |openssl enc -desx -base64

will ask for an encryption password and will generate an encyrpted digest.
To decode the password we use the following command:

MyPASS=$(echo "UVsB3dMG6VkX1+8889gjklo+g9g=" |openssl enc -desx -base64 -d)
 

Thursday 18 June 2015

Logging Server Connection counts

The below code is used to log connection counts on a SOA gateway (Actional in this case).
The aim is to try to see when the connections spike and have a kind of history benchmark to tell if things are looking fine.

below is a simple shell command to log established connection by IP address:

netstat -nat |grep ESTAB |cut -d ":" -f8,9 |sort |uniq -c

This is made to run on a crontab job every 5 mins.
The output is exposed (from a web server) to another script on a monitoring server that inserts this data into a mysql database for furture processing or reporting:

for rec in `curl http://mywebmonitor:10080/checkTC/soa/host_con_cnt 2>/dev/null |grep EST|tr -s " "|tr " " ":"`
do
        CON_CNT=`echo $rec|cut -d":" -f2`
        IP=`echo $rec|cut -d":" -f3`
        HOST=`nslookup ${IP}|grep name |cut -d "=" -f2 |sed 's/^ //g'|sed 's/.$//g'`
        WSPORT=`echo $rec|cut -d":" -f4`
        echo "INSERT INTO ssz_monitor.Actional_host_con_count (TCP_CON_CNT,HostName,IP,WS_Port,Actional_node,Timestamp) VALUES ('${CON_CNT}','${HOST}','${IP}','${WSPORT}','act05','`date +%Y%m%d%H%M `');"
done  >insert05.sql
mysql -u root -proot <insert05.sql






The data is inserted in the table and using HiediSQL we can export to analyze in Excel or any other spread sheet.
I am looking in creating reporting graphs out of this table, that would be much quicker to help if we have an issue.

Wednesday 22 April 2015

Stopping Apache 2.4 SSL proxy from chekcing backend Certificate

This post is intended for testing purposes only.
On production, apache should be allowed to check the cert as it is supposed to do by default.
This is one of the good hardening features that apache 2.4.x has over apache 2.2.x.

To stop all SSL validation on doing a proxy to an HTTPS back end; we need to use the following directives:

SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off

as of apache 2.4.7 the directive SSLProxyCheckPeerName overrides the PeerCN one and is also needed to be set to off.

Please check the below Stackoverflow link.
http://stackoverflow.com/questions/19294816/is-it-possible-to-ignore-an-apache-proxyd-certificate




Tuesday 31 March 2015

Rundeck example job definition

The below is a rundeck example job definition that uses options inside a script.

<joblist>
  <job>
    <id>3f6b1581-9b1d-4477-9980-627a95c0d676</id>
    <loglevel>INFO</loglevel>
    <sequence keepgoing='false' strategy='node-first'>
      <command>
        <scriptargs>${option.args_1}</scriptargs>
        <script><![CDATA[#Inline.sh
#!/bin/bash
echo "got this from the Job: @option.args_1@"
cat /dev/null >/tmp/${HOSTNAME}_rd_tst
echo "#inserting value from the RD job" >>/tmp/${HOSTNAME}_rd_tst
if [ "x${1}" = "x" ]
then
    echo "testid=100" >>/tmp/${HOSTNAME}_rd_tst
else
    echo "testid=${1}" >>/tmp/${HOSTNAME}_rd_tst
fi
echo "executed on ${HOSTNAME} at `date`"
echo "done"]]>
</script>
      </command>
    </sequence>
    <description>This job will create a file named ${HOSTNAME}_rd_tst on a remote node on temp folder and put in a key and default value of testid=100.</description>
    <name>Simple_file_key_value</name>
    <context>
      <project>Test_remote</project>
      <options>
        <option name='args_1' value='100' required='true' />
      </options>
    </context>
    <dispatch>
      <threadcount>1</threadcount>
      <keepgoing>false</keepgoing>
      <excludePrecedence>false</excludePrecedence>
      <rankOrder>ascending</rankOrder>
    </dispatch>
    <uuid>3f6b1581-9b1d-4477-9980-627a95c0d676</uuid>
    <nodefilters>
      <filter>beren.*</filter>
    </nodefilters>
  </job>
</joblist>

Monday 30 March 2015

Rundeck API small script

This is a demo script for using Rundeck and its API.

Rundeck API is a cumulative work that has api numbers from 1 to 12 up to now.
It will allow you to list and execute rundeck jobs remotely and also to monitor them remotely.
This will be very useful also for rundeck scripts that would call another remote rundeck jobs, this can be a good work around for remote execution when SSH is not allowed for security reasons.
Also would server to put your entire Ops jobs and infra under control using a simple web application.

The applications for this is limitless.
link this with my earlier post for nodeJS shell execution and u will have a lot of options to automation.

Below is a small example:

PROJECTS=`curl -H "Accept: application/json" http://beren:4440/api/1/projects?authtoken=It4kb1tIgw8gBpKI3rQhscKTp0OVYSNo |tr "}" "\n"|tr "," "\n"|grep name|cut -d":" -f2 |tr -d "\""`

#echo $PROJECTS
for proj in $PROJECTS
do
        #get all Jobs in all projects:
        echo "Project: $proj"
        curl "http://beren:4440/api/1/jobs?authtoken=It4kb1tIgw8gBpKI3rQhscKTp0OVYSNo&project=${proj}" #egrep "\<name>|\<job id="
done


To Run your job directly use a URL similar to below:

curl "http://beren:4440/api/1/job/61894b63-d687-4a39-a583-e0eba070339f/run?authtoken=It4kb1tIgw8gBpKI3rQhscKTp0OVYSNo"

Thursday 26 March 2015

Systemd vs SysV Linux services

Check the below commands for systemd new config:

[root@localhost systemd]# systemctl disable firewalld.service
rm '/etc/systemd/system/basic.target.wants/firewalld.service'
rm '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
[root@localhost systemd]#


[root@localhost systemd]# systemctl enable firewalld.service
ln -s '/usr/lib/systemd/system/firewalld.service' '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
ln -s '/usr/lib/systemd/system/firewalld.service' '/etc/systemd/system/basic.target.wants/firewalld.service'
[root@localhost systemd]#



[root@localhost systemd]# systemctl stop firewalld.service
[root@localhost systemd]#


[root@localhost systemd]# systemctl disable firewalld.service
rm '/etc/systemd/system/basic.target.wants/firewalld.service'
rm '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
[root@localhost systemd]#


[root@localhost systemd]# 
systemctl list-unit-files -t service ^C

Sunday 1 March 2015

of F5 BigIP and Session stickiness

F5 BigIP is well know for its robustness and superior performance in the the Loadbalancer business.

I was exposed to using it in a architecture similar to the one described below:
http://www.f5.com/pdf/deployment-guides/tomcat-dg.pdf

Actually, F5 would better serve as SSL offloading step and will mask the underlying Apache and Tomcat instances.

Two things needs to be considers:
1- Since we have 2 LB VIPs, each of them should maintain a separated cookie for session stickiness. this is to avoid one overwriting another.
2- If your app contains a lot of Ajax and asyncronous calls, OneConnect needs to be enabled on the Tomcat LB, so that the session stickiness decision is processed correctly for each request. this is becasue BigIP does the load balancing on the TCP connection rather than request basis.