Skip to content

Latest commit

 

History

History
 
 

daikon-audit

Audit Logging API

Audit Logging client library provides unified API for logging and processing audit events. It’s uses conventional logging frameworks to process audit events.

Currently supported logging frameworks:
  • logback 1.x

Usage

To start using Audit Logging it is necessary to:

  1. Add dependencies

  2. Create a configuration file

  3. Call the API

In most cases, the logs will be sent to LogStash which needs to have a special input configured (see Configuration section).

Adding dependencies

To start using Audit Logging client it’s necessary to add the next dependencies.

For logback 1.x:
<dependency>
    <groupId>org.talend.daikon</groupId>
    <artifactId>audit-logback</artifactId>
    <version>${audit.version}</version>
</dependency>

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

Configuration

Audit Logging client uses simple properties file for all its configuration (in future, if needed, yaml-based configuration may be implemented). It looks for the configuration file in the next places (in given order):

  1. Location specified in talend.logging.audit.config system property

  2. In classpath root, file named audit.properties

Here is an example of the configuration file.

If audit events are to be sent to LogStash as in this example, it has to have an additional input in its configuration:

input {
  http {
    response_headers => {
      "Access-Control-Allow-Origin" => "*"
      "Access-Control-Allow-Headers" => "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
      "Access-Control-Allow-Methods" => "*"
      "Access-Control-Allow-Credentials" => "*"
    }
    port => 8057
    type => "Audit"
    codec => "json"
  }
}
Note
Platform Service team provides LogServer with LogStash which is pre-configured for audit logging.

HTTP Configuration

HTTP appenders (logback) share the following configuration:

Property Description Default Value

connectTimeout

Optional (but recommended) HTTP connection timeout.

0

coreSize

Number of core threads in async mode (recommended to align it with max value).

1

encoding

Encoding used to create the basic token and content-type header, it is not used to encode the event.

null

keepAliveMs

How long to keep idle threads up in ms.

60000

maxSize

Number of max threads in async mode (recommended to align it with max value).

1

password

Optional password (requires an username) for basic authentication.

null

queueSize

Thread pool queue size. If negative it will be infinite, if zero it will be blocking when no thread is available, otherwise it is the number of allowed stacked events.

-1

readTimeout

Optional (but recommended) HTTP read timeout.

0

supportsSystemPropertiesOverride

Should current configuration be overridable with system properties. If true, you can use org.talend.logging.audit.impl.http.HttpEventSender.<property name> to override a value.

true

url

Target server URL where event are pushed to.

null

username

Optional username (requires a password) for basic authentication.

null

Logging a standard audit event

From applications perspective the basic use case is logging an audit event. If it’s one of the standard audit events, then all that is necessary to do is to create an instance of StandardEventAuditLogger using AuditLoggerFactory:

StandardEventAuditLogger auditLogger = AuditLoggerFactory.getEventAuditLogger(StandardEventAuditLogger.class);
...
auditLogger.loginSuccess();

This code logs audit message corresponding to login success event attaching values from MDC.

Passing context explicitly

If application needs to pass context explicitly rather than via MDC it can be done like this:

StandardEventAuditLogger auditLogger = AuditLoggerFactory.getEventAuditLogger(StandardEventAuditLogger.class);
...
Context ctx = ContextBuilder.create("user", "testuser").build();
auditLogger.loginSuccess(ctx);

For details, see Context and ContextBuilder.

Passing an exception as a parameter

If there’s an exception associated with audit event it can be passed as a parameter (some events require an exception as a parameter, but basically it can be passed to any event):

StandardEventAuditLogger auditLogger = AuditLoggerFactory.getEventAuditLogger(StandardEventAuditLogger.class);
...
} catch (Exception e) {
    Context ctx = ContextBuilder.create("user", "testuser").build();
    auditLogger.loginFail(ctx, ex);
    ...
}

Of course the context parameter doesn’t have to be there.

Defining a custom event

If application needs to log events which are not part of StandardEventAuditLogger it can extend this interface with new events:

public interface CustomEventAuditLogger extends StandardEventAuditLogger {

    @AuditEvent(category = "activity", message = "Flow has failed", level = LogLevel.WARNING)
    void flowFailed(Object... args);
}

AuditEvent is an annotation which defines event metadata.

Category parameter allows to group all events into few groups. Usually events fall into three categories: security, activity, failure. But any application is free to specify any string value as a category.

Log level is similar to the same concept from normal logging frameworks, but only has three values: INFO, WARNING or ERROR.

After defining new event the app needs to obtain an instance of this interface using the same factory method:

CustomEventAuditLogger auditLogger = AuditLoggerFactory.getEventAuditLogger(CustomEventAuditLogger.class);
...
Context ctx = ContextBuilder.create("flowId", "1234").build();
auditLogger.flowFailed(ctx);

Common audit events fields

We have defined in the AuditEvent the MDC common keys fields, all apps must use those keys for those actions {operation, resource, result} on user:

public interface CustomClass  {
	MDC.put(EventFields.USER, "user0");
	MDC.put(EventFields.OPERATION, "create user");
	MDC.put(EventFields.RESOURCE, "user");
	MDC.put(EventFields.RESULT, "success");
	...
}

Using simple API

For exceptional cases an application may log audit messages similarly to normal logging frameworks:

AuditLogger auditLogger = AuditLoggerFactory.getAuditLogger();
...
auditLogger.warning("security", "Account has been locked");

First parameter is audit event category. As with event APIs, a context and/or an exception may be passed as parameters.

Deactivating audit logging

If audit logging needs to be deactivated for some reason, it can be done by changing the configuration:

log.appender=none
Note
If application is running it needs to be restarted for this change to take effect.

Disable audit message in audit event

It is possible for an AbstractBackend to disable log messages if it doesn’t need it (e.g. performance consideration).

To do that, the implementation of the AbstractBackend have to override the method enableMessageFormat in order to return false (default value is true - backward compatibility considerations).