Audit Log
Bonita writes one JSON event per login, failed login and logout to a dedicated audit log, so that a SIEM can collect who authenticated, when and from where.
|
Available since Bonita 2025.1-u12 (technical id 10.3.12). |
What is recorded
Bonita writes an event for each:
-
login: successful or failed, including the login attempts rejected because the account is locked out by the brute-force login protection;
-
logout.
All the login paths of the Bonita web application are covered: the login page and the /loginservice endpoint, single sign-on (OIDC, SAML, CAS and Kerberos, Subscription editions only), and the platform administrator login. The guest user logins are not recorded.
The audit log is routed by the org.bonitasoft.runtime.audit logger, and each category of events has its own child logger: the authentication events are written at INFO level to the org.bonitasoft.runtime.audit.authentication logger. Both are on by default, in every edition and in single-node and cluster deployments alike.
Event format
Each event is a JSON object written on a single line. Its field names are modeled on the Elastic Common Schema, and fields without a value are left out. Example of a successful login (shown on several lines here):
{
"@timestamp": "2026-10-16T09:14:41.077Z",
"schema_version": "1",
"event": {"category": "authentication", "action": "login", "outcome": "success"},
"user": {"name": "walter.bates"},
"auth": {"method": "standard"},
"source": {"ip": "203.0.113.57"},
"user_agent": {"original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."},
"http": {"request": {"method": "POST"}},
"url": {"path": "/bonita/loginservice"},
"session": {"id_hash": "8802dac666a192b6b45ed25f30f9ca0562bad8996af207e18615c4509c450863"},
"host": {"name": "bonita-node-1"}
}
| Field | Description |
|---|---|
|
Time of the event, in UTC, with milliseconds. |
|
Version of the event format, |
|
Category of the event, |
|
|
|
|
|
Only set to |
|
The logged-in user, or the username that was attempted on a failed login. A failed single sign-on login for which the identity provider returned no username has none. |
|
|
|
Only for an |
|
IP address of the client, see Client IP address and User-Agent. |
|
|
|
HTTP method of the request. |
|
Path of the request, without query string or path parameters. |
|
SHA-256 hash of the session id, on successful logins and on logouts, to pair a logout with its login without writing the session identifier. |
|
Name of the server that handled the request. |
Where the events are written
Tomcat bundle
The events are written to <BUNDLE_HOME>/server/logs/audit.log, one event per line, and not to bonita.log. Like bonita.log, the file is rolled over every day and when it reaches 250 MB, as audit-<yyyy-MM-dd>-<n>.log.gz.
The routing is declared in server/conf/log4j2-appenders.xml:
<RollingRandomAccessFile fileName="${baseDir}/audit.log"
filePattern="${baseDir}/audit-%d{yyyy-MM-dd}-%i.log.gz"
name="Audit-File">
<!-- The message is already a JSON event: one event per line -->
<PatternLayout pattern="%m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingRandomAccessFile>
...
<Logger name="org.bonitasoft.runtime.audit" level="INFO" additivity="false">
<AppenderRef ref="Audit-File"/>
</Logger>
To also write the events with the other logs (bonita.log, and the console when enabled), remove additivity="false".
Old files are not deleted, as for bonita.log: apply the retention required by your audit policy, for example with a DefaultRolloverStrategy and a Delete action in the Audit-File appender:
<DefaultRolloverStrategy>
<Delete basePath="${baseDir}" maxDepth="1">
<IfFileName glob="audit-*.log.gz"/>
<IfLastModified age="P365D"/>
</Delete>
</DefaultRolloverStrategy>
Docker image
By default, the events are written on the standard output of the container, one JSON event per line with nothing around it, so that a log collector can read them as JSON. They are not repeated with the other logs.
As for the access logs, two environment variables switch the outputs on or off: AUDIT_LOG_STDOUT_ENABLED (default true) for the standard output, and AUDIT_LOG_FILES_ENABLED (default false) for /opt/bonita/logs/audit.log. Both can be enabled at the same time, for example to keep the file for retention while a log collector reads the standard output. To write the file only, also set AUDIT_LOG_STDOUT_ENABLED=false. With the file enabled, AUDIT_LOG_APPEND_HOSTNAME adds a folder named after the host to its path, so that the nodes of a cluster sharing the logs folder do not write the same file.
Old files are not deleted either: add the Delete action of the retention example to the Audit-File appender of a log4j2-appenders.xml mounted on /opt/bonita/conf/logs. With AUDIT_LOG_APPEND_HOSTNAME=true, the files are one folder deeper: use maxDepth="2" and glob="/audit-.log.gz".
Customized logging configuration
A log4j2-appenders.xml customized before Bonita 2025.1-u12 does not declare the audit logger and its appenders: the events are then written with the other logs, in the format of the other logs, and the AUDIT_LOG_* environment variables have no effect in the Docker image. Add the appenders and the org.bonitasoft.runtime.audit logger of the default file to it, for the Tomcat bundle as for a file mounted on /opt/bonita/conf/logs in the Docker image.
Switch the audit log off
Set the level of the org.bonitasoft.runtime.audit logger to OFF in log4j2-appenders.xml, for example in the Tomcat bundle:
<Logger name="org.bonitasoft.runtime.audit" level="OFF" additivity="false">
<AppenderRef ref="Audit-File"/>
</Logger>
To leave out the authentication events only, add their logger with the OFF level instead:
<Logger name="org.bonitasoft.runtime.audit.authentication" level="OFF"/>
Log4j2 reloads the file automatically, without restart. In the Docker image, you can also set AUDIT_LOG_STDOUT_ENABLED=false, with AUDIT_LOG_FILES_ENABLED not set or false, when creating the container. These variables do not change the level of the org.bonitasoft.runtime.audit.authentication logger in a mounted log4j2-appenders.xml.
Client IP address and User-Agent
source.ip is the address of the client as seen by Tomcat, and user_agent.original its User-Agent header. Bonita does not read the X-Forwarded-For header itself: behind a reverse proxy or a load balancer, source.ip is the address of the proxy unless Tomcat’s RemoteIpValve is configured in server/conf/server.xml. Set its internalProxies attribute to match your proxies only: a client that reaches Bonita without going through them could otherwise choose the IP address written in the audit log. In the Docker image, REMOTE_IP_VALVE_ENABLED=true enables the valve with Tomcat’s default trusted proxies (private and loopback address ranges).
When the Bonita UI Builder backend calls Bonita on behalf of a user, it sends the IP address and the User-Agent of the user’s browser in the X-Bonita-Client-Ip and X-Bonita-Client-User-Agent headers. These headers are ignored unless the following property is set to true, in bonita-platform-community-custom.properties (or with its environment variable):
| Property | Default | Description | Environment variable |
|---|---|---|---|
|
|
Uses the |
|
|
Only set it to |
Personal data and sensitive values
-
An event never contains the password, the request body, the query string or the path parameters (such as
jsessionid). -
The values coming from the request are truncated, ending with
…: username and identity provider to 256 characters, User-Agent to 512, URL path to 1024. -
The session id is hashed.
-
A failed login records the username that was typed.
Events that are not recorded
-
Failures at the identity provider with single sign-on: the user never reaches Bonita.
-
Session expiry. An explicit logout after the session has expired is not recorded either.
-
Bearer tokens rejected by the OIDC adapter.
-
Logins that do not go through the Bonita web application, such as calls to the Java
LoginAPIfrom code running in the server. -
Logouts of the sessions opened before Bonita was updated to 2025.1-u12, as their login was not recorded.
-
Login requests without any username: they are anonymous, not failed logins.