Apache log4j logo Apache logging services logo

Getting Started with Log4j Audit

This guide provides an overview of how to define events to be audited, generate the Java interfaces for those events and then use those interfaces to generate the audit events.

What you will build

You will build a project that consist of two modules. One module generates a jar that contains the audit catalog along with the Java interfaces that were created from the catalog. The second module generates a war that provides the service endpoints to perform remote audit logging and manage dynamic catalogs. You will install and use the catalog editor. Finally, you will also build a project that uses the audit event interfaces and generates audit events.

What you will need

  • About 15 minutes
  • A favorite text editor or IDE
  • JDK 1.8 or later
  • Apache Maven 3.0+

How to complete this guide

Create a directory for this guide:

    cd ~
    mkdir log4j-audit-guide
    cd log4j-audit-guide

Download and unzip the sample source repository, or clone it using Git:

    git clone https://github.com/apache/logging-log4j-audit-sample

Change to the root directory of the project and build it using Maven:

    cd logging-log4j-audit-sample
    mvn clean install

Three artifacts will have been created and installed into your local Maven repository:

  1. org.apache.logging.log4j:audit-service-api:1.0.0:jar
  2. org.apache.logging.log4j:audit-service-war:1.0.0:war
  3. org.apache.logging.log4j:audit-service:1.0.0:jar

The sample catalog can be found at audit-service-api/src/main/resources/catalog.json.

Inspect the build results

List the contents of audit-service-api/target/generated-sources/log4j-audit directory. The event interfaces generated from the catalog will be located in this directory. As an example, the Class that represents a transfer event looks like:

            package org.apache.logging.log4j.audit.event;

            import java.math.BigDecimal;
            import org.apache.logging.log4j.audit.AuditEvent;
            import org.apache.logging.log4j.audit.annotation.Constraint;
            import org.apache.logging.log4j.audit.annotation.MaxLength;
            import org.apache.logging.log4j.audit.annotation.RequestContext;
            import org.apache.logging.log4j.audit.annotation.Required;

            /**
            * Transfer between accounts
            * @author generated
            */
            @MaxLength(32)
            @RequestContext(key="hostName")
            @RequestContext(key="loginId", required=true)
            @RequestContext(key="ipAddress", constraints={@Constraint(constraintType="pattern", constraintValue="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")})
            @RequestContext(key="accountNumber", required=true)
            @RequestContext(key="userId", required=true)
            public interface Transfer extends AuditEvent {

                /**
                 * Amount : Amount to transfer
                 * @param amount Amount to transfer
                 */
                @Required
                public void setAmount(BigDecimal amount);

                /**
                 * From Account Number : Source of funds
                 * @param fromAccount Source of funds
                 */
                @Required
                public void setFromAccount(int fromAccount);

                /**
                 * To Account Number : Destination account
                 * @param toAccount Destination account
                 */
                @Required
                @Constraint(constraintType="minValue", constraintValue="1")
                public void setToAccount(int toAccount);
            }

Run an application that performs auditing

  1. Change to the sample-app diretory.
        cd sample-app
  2. Run the sample app and view the logs
        ./sample-app.sh  
        vi target/logs/audit.log

The output from the logs should look similar to:

          <128>1 2018-06-09T19:54:26.018-07:00 RalphGoers-MacBook-Pro.local SampleApp 18815 Audit [RequestContext@18060 hostName="RalphGoers-MacBook-Pro.local" ipAddress="192.168.1.15" loginId="testuser"][login@18060]
          <128>1 2018-06-09T19:54:26.021-07:00 RalphGoers-MacBook-Pro.local SampleApp 18815 Audit [RequestContext@18060 accountNumber="12345" hostName="RalphGoers-MacBook-Pro.local" ipAddress="192.168.1.15" loginId="testuser" userId="1111"][login@18060 completionStatus="Success"]
          <128>1 2018-06-09T19:54:26.026-07:00 RalphGoers-MacBook-Pro.local SampleApp 18815 Audit [RequestContext@18060 accountNumber="12345" hostName="RalphGoers-MacBook-Pro.local" ipAddress="192.168.1.15" loginId="testuser" userId="1111"][deposit@18060 account="123456" amount="100"]
          <128>1 2018-06-09T19:54:26.027-07:00 RalphGoers-MacBook-Pro.local SampleApp 18815 Audit [RequestContext@18060 accountNumber="12345" hostName="RalphGoers-MacBook-Pro.local" ipAddress="192.168.1.15" loginId="testuser" userId="1111"][deposit@18060 account="123456" amount="100" completionStatus="Success"]
Note that the formatting is completely controlled by the Log4j configuration. In this case, the RFC5424Layout was used.

The application that generated these logs is:

            public class SampleApp {

                public static void main(String[] args) throws Exception {
                    String hostName = NetUtils.getLocalHostname();
                    RequestContext.setHostName(hostName);
                    String inetAddress = InetAddress.getLocalHost().getHostAddress();
                    RequestContext.setIpAddress(inetAddress);
                    RequestContext.setLoginId("testuser");
                    Login login = LogEventFactory.getEvent(Login.class);
                    login.logEvent();
                    String result = login("testuser");
                    login.setCompletionStatus(result);
                    login.logEvent();
                    Deposit deposit = LogEventFactory.getEvent(Deposit.class);
                    deposit.setAccount(123456);
                    deposit.setAmount(new BigDecimal(100.00));
                    deposit.logEvent();
                    result = deposit(deposit);
                    deposit.setCompletionStatus(result);
                    deposit.logEvent();
                    RequestContext.clear();
                }

                private static String login(String user) {
                    RequestContext.setUserId("1111");
                    RequestContext.setAccountNumber(12345L);
                    return "Success";
                }

                private static String deposit(Deposit deposit) {
                return "Success";
            }

Deploy the Audit Service WAR

  1. Create a temporary directory and copy the audit service jar to it.
        cd ~
        mkdir auditService
        cd auditService
        cp ~/log4j-audit-guide/logging-audit-sample/audit-service/target/audit-service-1.0.0.jar .
  2. Use an editor to create a file named application.properties in the directory.
  3. Copy the following lines into the file. The value for remoteRepoUrl should the Git repo where your version of catalog.json should be stored. remoteRepoCatalogPath is the location within that Git repository where the catalog.json file resides. gitPassPhrase is the pass phrase needed to access the repository when SSH is used. gitUserName and gitPassPhrase are the credentials required to access the Git repository when using HTTP or HTTPS. If the credentials or pass phrase are not provided typically you will be able to view the catalog but not update it.
                  remoteRepoUrl=https://git-wip-us.apache.org/repos/asf/logging-log4j-audit-sample.git
                  remoteRepoCatalogPath=audit-service-api/src/main/resources/catalog.json
                  branch=<branchname>
                  gitUserName=
                  gitPassword=
                  gitPassPhrase=
  4. Start the application.
        java -jar audit-service-1.0.0.jar
  5. Wait for the application to start.
  6. Generate an audit event.
              curl -i -X POST -H 'Content-Type: application/vnd.apache.logging.log4j.audit+json; version="1.0"' \
              http://localhost:8080/event/log -d '{ "eventName": "transfer", "requestContextMap": {"loginId": "rgoers", "corpAccountNumber": "12345", "ipAddress": "127.0.0.1"}, "properties": {"toAccount": "111111", "fromAccount": "222222", "amount": "100.00"}}'
              
  7. The command should respond with
    HTTP/1.1 200
  8. View the audit log at logs/AuditService/audit.log. The audit event should be present in the file.

Run the Audit Catalog Editor

  1. Download the Log4j audit binary zip.
        wget http://www.apache.org/dist/logging/log4j-audit/1.0.0/apache-log4j-audit-1.0.0-bin.zip
  2. Unzip the contents.
        unzip apache-log4j-audit-1.0.0-bin.zip
  3. Copy the Log4j Catalog Editor jar to any directory.
        mkdir catalogEditor
        cd catalogEditor
        cp apache-log4j-audit-1.0.0-bin/log4j-catalog-editor-1.0.0.jar .
  4. Use an editor to create a file named application.properties in this directory.
  5. Copy the following lines into the file. The value for remoteRepoUrl should the Git repo where your version of catalog.json should be stored. remoteRepoCatalogPath is the location within that Git repository where the catalog.json file resides. gitPassPhrase is the pass phrase needed to access the repository when SSH is used. gitUserName and gitPassPhrase are the credentials required to access the Git repository when using HTTP or HTTPS. If the credentials or pass phrase are not provided typically you will be able to view the catalog but not update it.
        remoteRepoUrl=https://git-wip-us.apache.org/repos/asf/logging-log4j-audit-sample.git  
        remoteRepoCatalogPath=audit-service-api/src/main/resources/catalog.json
        branch=<branchname>
        gitUserName=  
        gitPassword=  
        gitPassPhrase=
  6. Start the application.
    java -jar log4j-catalog-editor-1.0.0.jar

Use the Catalog Editor

  1. Navigate to the edit attributes screen at http://localhost:8080/attributes. The screen should look like
  2. Navigate to the edit events screen at http://localhost:8080/events. The screen should look like