Package org.jwall

Source Code of org.jwall.Collector

/*
*  Copyright (C) 2007-2014 Christian Bockermann <chris@jwall.org>
*
*  This file is part of the  web-audit  library.
*
*  web-audit library is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 3 of the License, or
*  (at your option) any later version.
*
*  The  web-audit  library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.jwall;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.jwall.web.audit.AuditEventDispatcher;
import org.jwall.web.audit.io.AuditEventReader;
import org.jwall.web.audit.io.ConcurrentAuditReader;
import org.jwall.web.audit.io.ModSecurity2AuditReader;
import org.jwall.web.audit.net.AuditEventConsoleSender;


/**
*
* This is a small collector-tool that listens for events from
* the ModSecurity audit-engine and sends them back to a running
* ModSecurity Console.
*
* The tool is given a property-file on startup. This property-file
* needs to be setup with the host, port and auth-data of the
* console that you want to feed events to.
*
* A typical property-file for reading events from a concurrent
* audit-source looks like this:
*
* <pre>
*   org.modsecurity.console.host=webserver.example.com
*   org.modsecurity.console.port=8886
*   org.modsecurity.console.user=test
*   org.modsecurity.console.pass=sensor
*   org.modsecurity.collector.concurrent-log=/var/log/apache2/audit
*   org.modsecurity.collector.concurrent-index=/var/log/apache2/audit/index
* </pre>
*
* This will create a collector that expects all events to be written
* to unique-files below the directory <code>/var/log/apache2/audit</code>
* and an index written to <code>/var/log/apache2/audit/index</code>.
*
* The events that are read from this place will be sent to a console
* running on <code>webserver.example.com</code> at port <code>8886</code>.
* It will authenticate to the console using the login <code>test</code>
* and password <code>sensor</code>.
*
* These properties can also be given to the collector tool on the
* commandline:
*
* <pre>
*    java -Dorg.modsecurity.console.host=webserver.example.com
*         -Dorg.modsecurity.console.port=8886
*         -Dorg.modsecurity.console.user=test
*         ...
* </pre>
*
* @author Christian Bockermann &lt;chris@jwall.org&gt;
*
*/
public class Collector
{
    private static Logger log = LoggerFactory.getLogger( "Collector" );

    public static final String COLLECTOR_SERIAL_LOG = "org.modsecurity.collector.serial-log";
    public static final String COLLECTOR_CONCURRENT_LOG = "org.modsecurity.collector.concurrent-log";
    public static final String COLLECTOR_CONCURRENT_INDEX = "org.modsecurity.collector.concurrent-index";
    public static final String COLLECTOR_SEND_COMPLETE_LOG = "org.modsecurity.collector.send-complete-log";
    public static final String COLLECTOR_CONSOLE_URL = "org.modsecurity.collector.url";
    public static final String COLLECTOR_CONSOLE_USER = "org.modsecurity.collector.user";
    public static final String COLLECTOR_CONSOLE_PASSWORD = "org.modsecurity.collector.password";

    public final static String VERSION = "0.2.17";

    public static Properties p = new Properties();

    static URL url = null;
    static {
        try {
            new URL( "https://localhost:8443/rpc/auditLogReceiver");
        } catch (Exception e) {
            log.info( "Internal error: " + e.getLocalizedMessage() );
            e.printStackTrace();
        }
    }

    static String user = "test";
    static String pass = "sensor";

    /** This field enables debug-mode by specifying <code>-Dorg.modsecurity.Collector.DEBUG=1</code> on the commandline */
    public final static boolean DEBUG = System.getProperty("org.modsecurity.Collector.DEBUG") != null;



    /**
     *
     * This method is used to create an AuditEventReader that is
     * Bsed as the event-source. Based on the properties set, it
     * will return an instance that implements the <code>AuditEventReader</code>-interface,
     * like <code>ConcurrentAuditReader</code> or <code>ModSecurity2AuditReader</code>.
     *
     * @return An instance that implements the <code>AuditEventReader</code>-interface.
     * @throws Exception In case an error occurs or no properties have been set.
     */
    public static AuditEventReader createAuditEventReader()
    throws Exception
    {
        boolean tail = true;
        if( "true".equals( p.getProperty( Collector.COLLECTOR_SEND_COMPLETE_LOG ) ) ){
            System.err.println( "Sending all audit-log entries!" );
            tail = false;
        }

        AuditEventReader src = null;

        if( "stdin".equals( p.getProperty( COLLECTOR_SERIAL_LOG ) ) ){
            System.out.println( "Reading from standard input..." );
            src = new ModSecurity2AuditReader( System.in, true );
            return src;
        }

        if( p.getProperty( COLLECTOR_SERIAL_LOG ) != null ){

            String input = p.getProperty( COLLECTOR_SERIAL_LOG );
            if( "stdin".equalsIgnoreCase( input ) ){
                System.out.println("Reading ModSecurity 2.x serial audit-log from standard input..." );
                src = new ModSecurity2AuditReader( System.in );
                return src;
            }

            File f = new File( p.getProperty( COLLECTOR_SERIAL_LOG ) );
            if( ! f.canRead() )
                throw new Exception("Cannot open "+f.getAbsoluteFile()+" for reading!");



            src = new ModSecurity2AuditReader( f, tail );
            return src;
        }

        if( p.getProperty( COLLECTOR_CONCURRENT_LOG ) != null && p.getProperty(COLLECTOR_CONCURRENT_INDEX) != null){

            String index = p.getProperty( COLLECTOR_CONCURRENT_INDEX );
            File dat = new File( p.getProperty( COLLECTOR_CONCURRENT_LOG ) );
            if( ! dat.canRead() )
                throw new Exception("Cannot open concurrent data-directory '"+dat.getAbsolutePath()+"' for reading!");

            if( "stdin".equalsIgnoreCase( index ) ){
                System.out.println( "Reading summaries from standard input..." );
                src = new ConcurrentAuditReader( System.in, dat );

            } else {

                File idx = new File( p.getProperty( COLLECTOR_CONCURRENT_INDEX ) );
                if( ! idx.canRead() )
                    throw new Exception("Cannot open concurrent index-file "+idx.getAbsoluteFile()+" for reading!");

                src = new ConcurrentAuditReader( dat, idx, tail );
            }
        }

        return src;
    }



    /**
     *
     * This method checks all the properties, found in the given file
     * <code>pf</code>. If the file does not conform to a java-property
     * file or does not contain the required properties, then
     * <code>false</code> is returned.
     *
     * If the file is null, cannot be read or any other error occurs
     * while reading the file, an exception will be thrown.
     *
     * The method returns <code>true</code>, iff all required properties
     * are set within the file.
     *
     * @param pf The file to read properties from.
     * @return <code>true</code> if all required properties are contained in the file.
     * @throws Exception In case any error occurs while accessing the file.
     */
    public static boolean checkProperties( File pf )
    throws Exception
    {
        boolean ok = true;
        p = new Properties();
        File f = pf;
        if( f == null )
            f = new File( "sensor.properties" );

        if( ! f.exists() ){

            URL url = new URL( "https://localhost:8886/rpc/auditLogReceiver" );

            p.setProperty( COLLECTOR_CONSOLE_USER, "test" );
            p.setProperty( COLLECTOR_CONSOLE_PASSWORD, "sensor" );
            p.setProperty( COLLECTOR_SERIAL_LOG, "/var/log/audit.log");
            p.setProperty( COLLECTOR_CONSOLE_URL, url.toString() );

            FileOutputStream fos = new FileOutputStream( f );
            if( fos != null ){
                p.store( fos, "Automatically created initial config. Please edit for your needs!!");
                fos.close();
            }
           
            log.info("Created default configuration in "+f.getAbsoluteFile()+"!");
            log.info("Please adjust config for your environment and restart.");
            System.exit(0);
        }

        if( ! f.canRead() ){
            log.info("Properties file "+f.getAbsoluteFile()+" cannot be read!");
            ok = false;
        } else {
            log.debug("Reading properties from "+f.getAbsoluteFile());
        }

        try {
            FileInputStream fis = new FileInputStream( f );
            if( fis != null ){
                p.load( fis );
                fis.close();
            }

        } catch (Exception e) {
            log.error( "Error while reading from " + f.getAbsoluteFile() + ": " + e.getMessage() );
            ok = false;
        }

        //
        // Environment variables overwrite file-properties!
        //
        Iterator<Object> it = System.getProperties().keySet().iterator();
        while( it.hasNext() ){
            String key = (String) it.next();
            if( key.startsWith( "org.modsecurity" ) ) {
                p.setProperty( key , System.getProperty( key ) );
                log.info( "Found system-property \"" + key + "\" = " + System.getProperty( key ) );
            }
        }

        it = p.keySet().iterator();
        while( it.hasNext() ){
            String key = (String)it.next();
            System.err.println(" " + key + " = " + p.getProperty( key ) );
            if( key.startsWith( "org.modsecurity" ) )
                log.debug( "Property \"" + key + "\" = " + p.getProperty( key ) );
        }

        if( p.getProperty( COLLECTOR_CONSOLE_URL ) != null ){
            url = new URL( p.getProperty( COLLECTOR_CONSOLE_URL ) );
            log.info( "Found console url " + url );
            p.setProperty( org.jwall.web.audit.net.AuditEventConsoleSender.CONSOLE_HOST, url.getHost() );
            p.setProperty( org.jwall.web.audit.net.AuditEventConsoleSender.CONSOLE_PORT, url.getPort() + "" );
            p.setProperty( org.jwall.web.audit.net.AuditEventConsoleSender.CONSOLE_CONNECTION_SSL, url.getProtocol().toLowerCase().startsWith( "https" ) + "" );
        } else {
            throw new Exception("Property \"" + COLLECTOR_CONSOLE_URL + "\" not found!" );
        }

        user = p.getProperty( org.jwall.web.audit.net.AuditEventConsoleSender.CONSOLE_USER );
        if( user == null ){
            log.warn("Warning: No user-name specified, using default ('test').");
            user = "test";
        }

        pass = p.getProperty( org.jwall.web.audit.net.AuditEventConsoleSender.CONSOLE_PASS );
        if( pass == null ){
            log.warn("Warning: No password specified, using default ('sensor').");
            pass = "sensor";
        }

        Enumeration<Object> en = p.keys();
        while( en.hasMoreElements() ){
            String key = (String) en.nextElement();
            log.debug(key+" = "+p.getProperty(key));
        }

        try {
            String ser = p.getProperty( COLLECTOR_SERIAL_LOG );
            String con = p.getProperty( COLLECTOR_CONCURRENT_LOG );
            String conIdx = p.getProperty( COLLECTOR_CONCURRENT_INDEX );

            if( ser == null ){
                log.debug("No serial-log specified.");

                if( con == null )  
                    log.debug("Warning: No concurrent auditlog specified!");


                if( conIdx == null )
                    log.debug("Warning: No concurrent auditlog index file specified!");
            }

            if( ser == null && con == null && conIdx == null ){
                log.debug("Error: No audit-event-source specified!");
                throw new Exception("Missing audit-event-source!");
            }

        } catch (Exception e){
            e.printStackTrace();
        }

        return ok;
    }


    public static String getProperty( String key ){
        return p.getProperty( key );
    }

    /**
     *
     * This is the entrypoint for the Collector-tool. It expects
     * <code>args[0]</code> to be the name or path of a property-file
     * containing information about the remote-console and the source
     * to read audit-events from.
     *
     * If the file does not contains the desired information, the
     * Collector will exit.
     *
     * @param args The commandline arguments.
     *
     */
    public static void main(String[] args) {

        try {
            File pf = null;
            if( args.length > 0 )
                pf = new File(args[0]);
            else {
                InputStream in = Collector.class.getResourceAsStream( "/org/jwall/collector-usage.txt" );
                if( in != null ){

                    BufferedReader r = new BufferedReader( new InputStreamReader( in ) );
                    String line = r.readLine();
                    while( line != null ){
                        System.out.println( line );
                        line = r.readLine();
                    }
                    r.close();

                } else {
                    System.out.println("\nSyntax error. Please see help for instructions on starting the collector!\n" );
                }

                return;
            }

            //log.setLevel( Level.FINEST );
            System.err.println("Reading settings from " + pf.getAbsolutePath() );

            boolean ok = checkProperties(pf);
            if( ! ok ){
                log.info("Error in configuration.");
            }

            AuditEventReader src = createAuditEventReader();
            if( src == null ){
                log.info("  Error: No valid audit-event-source specified!");
                log.info("  Error: Please check your config and try again.");
                System.exit(-1);
            }



            int port = url.getPort() > 0 ? url.getPort() : 8443;

            if( System.getProperty( "DEBUG" ) != null ){
                log.info( "Sending events to URL " + url.toString() );
                log.info( "   host = " + url.getHost() );
                log.info( "   port = " + port );
                log.info( "   user = " + user );
                log.info( "   pass = " + pass );
            }

            AuditEventConsoleSender sender = new AuditEventConsoleSender( url.getHost(), port, user, pass );
            AuditEventDispatcher d = new AuditEventDispatcher( src );

            //
            //
            d.setPersistent( !"true".equals( p.getProperty( Collector.COLLECTOR_SEND_COMPLETE_LOG ) ) );


            d.addAuditEventListener( sender );
            d.start();

        } catch (Exception e){
            e.printStackTrace();
            System.exit(-1);
        }
    }
}
TOP

Related Classes of org.jwall.Collector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.