org.jwall.web.audit - Overview

This little page is intended to give an overview of the API of the web-audit library (version 0.2.9). It is not complete and might change in future versions as though the basic concepts will remain. Currently this page is a work in progress as is the web-audit library.

AuditEvent

The most basic interface defined within the library is AuditEvent. This is an abstract interface that represents an event instance within the Java environment. It provides several methods for accessing all properties of the request/response that the event is associated with. AuditEvent is defined as interface to abstract from the underlying data-storage. The basic implementation provided by AuditEventImpl holds all the data in strings and parses these strings to create hashmaps to provide access to the event-properties.

The generic get(String)-method can be used to retrieve a certain header-field or other property. The properties names' are defined as constants within the global interface org.jwall.web.audit.ModSecurity. This way you can check the user-agent of a request that is given within AuditEvent evt by calling

      // read an event from a reader
      AuditEvent evt = reader.readEvent();

      // if an event is returned retrieve the user-agent, sent in the request
      //
      if( evt != null ){

          String userAgent = evt.get( ModSecurity.REQUEST_HEADER_USER_AGENT );
                    
      }

The argument given to get(String) here is a constant that simply resembles the ModSecurity collection-variable REQUEST_HEADER:User-Agent and could be replaced by this string. However it is encouraged to use these constants for later compability.

Event Handling

For managing the events, the web-audit library defines several interfaces that can be used to easily build processing-chains in the sense of unix-pipes. The following sketch shows an example of the event-handling provided by the source- and a listener-interfaces of the library.

Receiving Events

Receiving events in this context does not refer to sending events over the network, but simply for a class being notified when a new event arrives. To receive any events a class has to implement the AuditEventListener-interface which simply consists of the method

    public void eventArrived( AuditEvent evt )

This method is called whenever an event is given to a listener-class that previously registered itself to an event-source.

Dispatching Events

The storage/distribution of events is done by classes that implement the AuditEventSource interface. An asynchronous way for dispatching events is provided with the AuditEventDispatcher-class. It offers methods to register listeners for receiving audit events and works in a separate thread. An example for a class that extends this mechanism can be found with the BufferedAuditEventSource. This will actively try to read events from a reader an dispatch them to all registered listeners. Use of this buffered source is describe below.

Event Filtering

It is in some cases helpful to filter out certain events that a listener is not really interested in. For example, a listener that is observing a certain URL might want to ignore all events that do not belong to this url.

Filtering is provided by the AuditEventFilter-interface. It simply consists of a method matches(AuditEvent) that returns true, if the given audit-event matches the filter. A filter can thus easily be created by implementing this method, for example filtering for a specific url can be done like this:

     AuditEventFilter filter = new AuditEventFilter(){
         public boolean matches( AuditEvent evt ){

             String url = evt.get( ModSecurity.REQUEST_URI );
             if( url == null )
                 return false;
             
	     return url.startsWith( "/cgi-bin" );
         }
     };

A generic filter is implemented within the library by the AuditEventRegexpFilter-class.

Layout of I/O-Classes

The I/O-mechanisms provided by libmodsecurity consists of a simple AuditEventReader-interface which defines the readEvent-method for parsing one event. The implementing classes can be seen as passive components which try to return the next event from their input-data each time their readEvent-method is called. They will return null in case no more events can be read or throw an exception if an I/O-error occurs.

The classes that are implementing this interface provided with the library are ModSecurity2AuditReader and ConcurrentAuditReader and can be used to read events from either the serial- or the concurrent audit-log format.

Buffered I/O 

For active I/O the library provides the BufferedAuditEventSource which can be seen as a daemon-thread that constantly reads events from a given reader and stores them in an internal queue. This can be thought of as a read-ahead-reader that can be easily created using one of the readers described above:

      // create a serial-log reader
      AuditEventReader reader = new ModSecurity2AuditReader( new File("/var/log/audit.log") );

      // create the read-ahead reader thread
      //
      BufferedAuditEventSource src = new BufferedAuditEventSource( reader );

The buffered source immediately starts reading in a separate thread. The class also implements the AuditEventDispatcher-interface which can be used to register event-listeners that are to be notified if events are read:

      // register a listener to the buffered event source that prints out
      // all events that are read
      //
      src.addEventListener( new AuditEventListener(){

          public void eventArrived( AuditEvent evt ){

              System.out.println( "event arrived: " + evt );

          }
      });