Skip to content

Commit 54c74fe

Browse files
authored
Merge pull request #215 from kovaceviccz/add-json-handler-to-audit-logging
Add JSON handler to audit logging
2 parents f27bca6 + cdf7525 commit 54c74fe

File tree

6 files changed

+577
-1
lines changed

6 files changed

+577
-1
lines changed

openam-audit/openam-audit-configuration/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* information: "Portions copyright [year] [name of copyright owner]".
1414
*
1515
* Copyright 2014-2016 ForgeRock AS.
16-
* Portions copyright 2018-2023 Wren Security
16+
* Portions copyright 2018-2025 Wren Security
1717
-->
1818
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
1919
<modelVersion>4.0.0</modelVersion>
@@ -48,6 +48,11 @@
4848
<artifactId>forgerock-audit-handler-csv</artifactId>
4949
</dependency>
5050

51+
<dependency>
52+
<groupId>org.wrensecurity.commons</groupId>
53+
<artifactId>forgerock-audit-handler-json</artifactId>
54+
</dependency>
55+
5156
<dependency>
5257
<groupId>org.wrensecurity.commons</groupId>
5358
<artifactId>forgerock-audit-handler-syslog</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* The contents of this file are subject to the terms of the Common Development and
3+
* Distribution License (the License). You may not use this file except in compliance with the
4+
* License.
5+
*
6+
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7+
* specific language governing permission and limitations under the License.
8+
*
9+
* When distributing Covered Software, include this CDDL Header Notice in each file and include
10+
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11+
* Header, with the fields enclosed by brackets [] replaced by your own identifying
12+
* information: "Portions copyright [year] [name of copyright owner]".
13+
*
14+
* Copyright 2025 Wren Security. All rights reserved.
15+
*/
16+
package org.forgerock.openam.audit.events.handlers;
17+
18+
import static com.iplanet.am.util.SystemProperties.CONFIG_PATH;
19+
import static com.sun.identity.shared.Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR;
20+
import static com.sun.identity.shared.datastruct.CollectionHelper.getBooleanMapAttr;
21+
import static com.sun.identity.shared.datastruct.CollectionHelper.getIntMapAttr;
22+
import static com.sun.identity.shared.datastruct.CollectionHelper.getLongMapAttr;
23+
import static com.sun.identity.shared.datastruct.CollectionHelper.getMapAttr;
24+
25+
import com.iplanet.am.util.SystemProperties;
26+
import com.sun.identity.shared.debug.Debug;
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.Set;
31+
import javax.inject.Singleton;
32+
import org.forgerock.audit.AuditException;
33+
import org.forgerock.audit.events.handlers.AuditEventHandler;
34+
import org.forgerock.audit.handlers.json.JsonAuditEventHandler;
35+
import org.forgerock.audit.handlers.json.JsonAuditEventHandlerConfiguration;
36+
import org.forgerock.audit.handlers.json.JsonAuditEventHandlerConfiguration.EventBufferingConfiguration;
37+
import org.forgerock.openam.audit.AuditEventHandlerFactory;
38+
import org.forgerock.openam.audit.configuration.AuditEventHandlerConfiguration;
39+
40+
/**
41+
* This factory is responsible for creating an instance of the {@link JsonAuditEventHandler}.
42+
*/
43+
@Singleton
44+
public final class JsonAuditEventHandlerFactory implements AuditEventHandlerFactory {
45+
46+
private static final Debug DEBUG = Debug.getInstance("amAudit");
47+
48+
@Override
49+
public AuditEventHandler create(final AuditEventHandlerConfiguration configuration) throws AuditException {
50+
Map<String, Set<String>> attributes = configuration.getAttributes();
51+
JsonAuditEventHandlerConfiguration jsonHandlerConfiguration = new JsonAuditEventHandlerConfiguration();
52+
jsonHandlerConfiguration.setLogDirectory(getLogDirectory(attributes));
53+
jsonHandlerConfiguration.setTopics(attributes.get("topics"));
54+
jsonHandlerConfiguration.setName(configuration.getHandlerName());
55+
jsonHandlerConfiguration.setEnabled(getBooleanMapAttr(attributes, "enabled", true));
56+
jsonHandlerConfiguration.setElasticsearchCompatible(
57+
getBooleanMapAttr(attributes, "elasticsearchCompatible", false));
58+
jsonHandlerConfiguration.setRotationRetentionCheckInterval(
59+
getIntMapAttr(attributes, "rotationRetentionCheckInterval", 20, DEBUG) + " s");
60+
setFileRotationPolicies(jsonHandlerConfiguration, attributes);
61+
setFileRetentionPolicies(jsonHandlerConfiguration, attributes);
62+
jsonHandlerConfiguration.setBuffering(getBufferingConfiguration(attributes));
63+
return new JsonAuditEventHandler(jsonHandlerConfiguration, configuration.getEventTopicsMetaData());
64+
}
65+
66+
private String getLogDirectory(Map<String, Set<String>> attributes) {
67+
String location = getMapAttr(attributes, "location", "");
68+
String baseDir = SystemProperties.get(CONFIG_PATH);
69+
if (baseDir != null) {
70+
location = location.replace("%BASE_DIR%", baseDir);
71+
}
72+
String serverUri = SystemProperties.get(AM_SERVICES_DEPLOYMENT_DESCRIPTOR);
73+
if (serverUri != null) {
74+
location = location.replace("%SERVER_URI%", serverUri);
75+
}
76+
return location;
77+
}
78+
79+
private void setFileRotationPolicies(JsonAuditEventHandlerConfiguration jsonHandlerConfiguration,
80+
Map<String, Set<String>> attributes) throws AuditException {
81+
jsonHandlerConfiguration.getFileRotation()
82+
.setRotationEnabled(getBooleanMapAttr(attributes, "rotationEnabled", true));
83+
jsonHandlerConfiguration.getFileRotation()
84+
.setMaxFileSize(getLongMapAttr(attributes, "rotationMaxFileSize", 100000000L, DEBUG));
85+
jsonHandlerConfiguration.getFileRotation()
86+
.setRotationFilePrefix(getMapAttr(attributes, "rotationFilePrefix", ""));
87+
jsonHandlerConfiguration.getFileRotation()
88+
.setRotationFileSuffix(getMapAttr(attributes, "rotationFileSuffix", "-yyyy.MM.dd-HH.mm.ss"));
89+
jsonHandlerConfiguration.getFileRotation()
90+
.setRotationInterval(parseRotationInterval(getMapAttr(attributes, "rotationInterval", "-1")));
91+
92+
List<String> times = new ArrayList<>();
93+
Set<String> rotationTimesAttribute = attributes.get("rotationTimes");
94+
if (rotationTimesAttribute != null && !rotationTimesAttribute.isEmpty()) {
95+
for (String rotationTime : rotationTimesAttribute) {
96+
times.add(rotationTime + " seconds");
97+
}
98+
jsonHandlerConfiguration.getFileRotation().setRotationTimes(times);
99+
}
100+
}
101+
102+
private String parseRotationInterval(String interval) throws AuditException {
103+
try {
104+
Long intervalAsLong = Long.valueOf(interval);
105+
106+
if (intervalAsLong <= 0) {
107+
// If interval is 0 or a negative value, the feature is disabled
108+
return "disabled";
109+
} else {
110+
// If interval is a positive number, add seconds as the time unit
111+
return interval + " seconds";
112+
}
113+
} catch (NumberFormatException nfe) {
114+
throw new AuditException("Attribute 'rotationInterval' is invalid: " + interval);
115+
}
116+
}
117+
118+
private void setFileRetentionPolicies(JsonAuditEventHandlerConfiguration jsonHandlerConfiguration,
119+
Map<String, Set<String>> attributes) {
120+
jsonHandlerConfiguration.getFileRetention()
121+
.setMaxNumberOfHistoryFiles(getIntMapAttr(attributes, "retentionMaxNumberOfHistoryFiles", 1, DEBUG));
122+
jsonHandlerConfiguration.getFileRetention()
123+
.setMaxDiskSpaceToUse(getLongMapAttr(attributes, "retentionMaxDiskSpaceToUse", -1L, DEBUG));
124+
jsonHandlerConfiguration.getFileRetention()
125+
.setMinFreeSpaceRequired(getLongMapAttr(attributes, "retentionMinFreeSpaceRequired", -1L, DEBUG));
126+
}
127+
128+
private EventBufferingConfiguration getBufferingConfiguration(Map<String, Set<String>> attributes) {
129+
EventBufferingConfiguration bufferingConfiguration = new EventBufferingConfiguration();
130+
bufferingConfiguration.setMaxSize(getIntMapAttr(attributes, "maxSize", 10000, DEBUG));
131+
bufferingConfiguration.setWriteInterval(getIntMapAttr(attributes, "writeInterval", 1000, DEBUG) + " millis");
132+
return bufferingConfiguration;
133+
}
134+
135+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#
2+
# The contents of this file are subject to the terms of the Common Development and
3+
# Distribution License (the License). You may not use this file except in compliance with the
4+
# License.
5+
#
6+
# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7+
# specific language governing permission and limitations under the License.
8+
#
9+
# When distributing Covered Software, include this CDDL Header Notice in each file and include
10+
# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11+
# Header, with the fields enclosed by brackets [] replaced by your own identifying
12+
# information: "Portions copyright [year] [name of copyright owner]".
13+
#
14+
# Copyright 2025 Wren Security. All rights reserved.
15+
#
16+
17+
########################################################################################################################
18+
# Common handler section properties
19+
########################################################################################################################
20+
commonHandler=enabled
21+
commonHandler=topics
22+
23+
########################################################################################################################
24+
# Common handler plugin section properties
25+
########################################################################################################################
26+
commonHandlerPlugin=handlerFactory
27+
28+
########################################################################################################################
29+
# JSON handler section properties
30+
########################################################################################################################
31+
jsonConfig=location
32+
jsonConfig=elasticsearchCompatible
33+
jsonConfig=rotationRetentionCheckInterval
34+
jsonFileRotation=rotationEnabled
35+
jsonFileRotation=rotationMaxFileSize
36+
jsonFileRotation=rotationFilePrefix
37+
jsonFileRotation=rotationFileSuffix
38+
jsonFileRotation=rotationInterval
39+
jsonFileRotation=rotationTimes
40+
jsonFileRetention=retentionMaxNumberOfHistoryFiles
41+
jsonFileRetention=retentionMaxDiskSpaceToUse
42+
jsonFileRetention=retentionMinFreeSpaceRequired
43+
jsonBuffering=bufferingMaxSize
44+
jsonBuffering=bufferingWriteInterval

openam-audit/openam-audit-configuration/src/main/resources/audit.properties

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# information: "Portions copyright [year] [name of copyright owner]".
1212
#
1313
# Copyright 2015-2016 ForgeRock AS.
14+
# Portions copyright 2025 Wren Security.
1415

1516

1617
########################################################################################################################
@@ -42,6 +43,7 @@ handler.name.jdbc=JDBC
4243
handler.name.syslog=Syslog
4344
handler.name.elasticsearch=Elasticsearch
4445
handler.name.jms=JMS
46+
handler.name.json=JSON
4547

4648
# Additions to handler properties. Other properties are stored in commons audit translation.properties.
4749
audit.handlers.jdbc.databaseType.help=Select the database to use for logging audit events.
@@ -117,6 +119,27 @@ section.label.AuditService.Organization.csvFileRetention=File Retention
117119
section.label.AuditService.Organization.csvBuffering=Buffering
118120
section.label.AuditService.Organization.csvSecurity=Tamper Evident Configuration
119121

122+
########################################################################################################################
123+
# JSON handler section properties
124+
########################################################################################################################
125+
sections.JSON=\
126+
commonHandler \
127+
jsonConfig \
128+
jsonFileRotation \
129+
jsonFileRetention \
130+
jsonBuffering \
131+
commonHandlerPlugin
132+
133+
section.label.AuditService.Global.jsonConfig=JSON Configuration
134+
section.label.AuditService.Global.jsonFileRotation=File Rotation
135+
section.label.AuditService.Global.jsonFileRetention=File Retention
136+
section.label.AuditService.Global.jsonBuffering=Buffering
137+
138+
section.label.AuditService.Organization.jsonConfig=JSON Configuration
139+
section.label.AuditService.Organization.jsonFileRotation=File Rotation
140+
section.label.AuditService.Organization.jsonFileRetention=File Retention
141+
section.label.AuditService.Organization.jsonBuffering=Buffering
142+
120143
########################################################################################################################
121144
# Syslog handler section properties
122145
########################################################################################################################
@@ -252,6 +275,23 @@ handler.factory=Factory Class Name
252275
handler.factory.help=The fully qualified class name of the factory responsible for creating the Audit Event \
253276
Handler. The class must implement org.forgerock.openam.audit.AuditEventHandlerFactory.
254277

278+
# JSON handler configuration
279+
audit.handlers.json.logDirectory=Log Directory
280+
audit.handlers.json.logDirectory.help=Directory in which to store audit log JSON files
281+
audit.handlers.json.elasticsearchCompatible=ElasticSearch JSON Format Compatible
282+
audit.handlers.json.elasticsearchCompatible.help=JSON format should be transformed to be compatible with \
283+
ElasticSearch format restrictions.
284+
audit.handlers.json.rotationRetentionCheckInterval=Rotation and Retention Check Interval
285+
audit.handlers.json.rotationRetentionCheckInterval.help=Interval for periodically checking file rotation and retention \
286+
policies
287+
audit.handlers.json.buffering=Buffering
288+
audit.handlers.json.buffering.help=Configuration for optional event buffering.
289+
audit.handlers.json.buffering.maxSize=Buffer Size
290+
audit.handlers.json.buffering.maxSize.help=Size of the event buffer queue
291+
audit.handlers.json.buffering.writeInterval=Write interval
292+
audit.handlers.json.buffering.writeInterval.help=Interval at which buffered events are written to a file, \
293+
in milliseconds.
294+
255295
# JDBC handler configuration
256296
audit.handlers.jdbc.databaseType=Database Type
257297
audit.handlers.jdbc.databaseType.help.txt=Identifies the database in use (MySQL, Oracle SQL)

0 commit comments

Comments
 (0)