Direct Audit Information to a JMS Broker
This sample shows how to configure a Java Message Service (JMS) audit event handler to direct audit information to a JMS broker.
JMS is an API that supports Java-based peer-to-peer messages between clients. The JMS API can create, send, receive, and read messages, reliably and asynchronously. You can set up a JMS audit event handler to publish messages that comply with the Java Message Service Specification Final Release 1.1.
This sample demonstrates the use of the JMS audit event handler. In the sample you will set up communication between IDM and an external JMS Message Broker, as well as Apache Active MQ as the JMS provider and message broker.
Note
JMS topics are not related to ForgeRock audit event topics. The ForgeRock implementation of JMS topics uses the publish/subscribe messaging domain to direct messages to the JMS audit event handler. In contrast, ForgeRock audit event topics specify categories of events.
Dependencies for JMS Messaging
The JMS audit event handler requires ActiveMQ, and a number of dependencies, that are bundled with the ActiveMQ delivery. This section lists the dependencies, and where they must be installed in the IDM instance. If you use a different ActiveMQ version, you might need to download the corresponding dependencies separately.
Download the following files:
ActiveMQ. This sample was tested with ActiveMQ Classic 5.16.1.
The most recent
bnd
JAR file from https://repo1.maven.org/maven2/biz/aQute/bnd/biz.aQute.bnd/. The bnd utility lets you create OSGi bundles for libraries that do not yet support OSGi.
Unpack the ActiveMQ archive. For example:
tar -zxvf ~/Downloads/apache-activemq-5.16.1-bin.tar
Create a temporary directory, move the ActiveMQ Client, and
bnd
JAR files to that directory, then change to that directory:mkdir ~/Downloads/tmp mv ~/Downloads/apache-activemq-5.16.1/lib/activemq-client-5.16.1.jar ~/Downloads/tmp/ mv biz.aQute.bnd-version.jar ~/Downloads/tmp/ cd ~/Downloads/tmp/
Create an OSGi bundle as follows:
In a text editor, create a BND file named
activemq.bnd
and save it to the current directory. The file should have the following contents:version=5.16.1 Export-Package: *;version=${version} Bundle-Name: ActiveMQ :: Client Bundle-SymbolicName: org.apache.activemq Bundle-Version: ${version}
Your
tmp/
directory should now contain the following files:ls ~/Downloads/tmp/
activemq-client-5.16.1.jar activemq.bnd biz.aQute.bnd-version.jar
In that same directory, create the OSGi bundle archive file as follows:
java -jar biz.aQute.bnd-version.jar \ wrap --properties activemq.bnd \ --output activemq-client-5.16.1-osgi.jar \ activemq-client-5.16.1.jar
Copy the resulting
activemq-client-5.16.1-osgi.jar
file to theopenidm/bundle
directory:cp activemq-client-5.16.1-osgi.jar /path/to/openidm/bundle/
Copy the required dependencies from the extracted ActiveMQ archive to the
openidm/bundle
directory:cp ~/Downloads/apache-activemq-5.16.1/lib/geronimo-j2ee-management_1.1_spec-1.0.1.jar /path/to/openidm/bundle/ cp ~/Downloads/apache-activemq-5.16.1/lib/hawtbuf-1.11.jar /path/to/openidm/bundle/ cp ~/Downloads/apache-activemq-5.16.1/lib/optional/jmdns-3.4.1.jar /path/to/openidm/bundle cp ~/Downloads/apache-activemq-5.16.1/lib/optional/commons-net-3.7.2.jar /path/to/openidm/bundle
Configure SSL for ActiveMQ
This configuration provides a connection to the ActiveMQ server instance with TLSv1.3.
In the directory where you unpacked ActiveMQ, edit the
conf/activemq.xml
file as follows:In the
<brokers>
element, add an<sslContext>
:<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}"> ... <sslContext> <sslContext keyStore="file:${activemq.conf}/broker.ks" keyStorePassword="password"/> </sslContext> ... </broker>
In the
<transportConnectors>
element, add anssl
<transportConnector>
:<transportConnectors> ... <transportConnector name="ssl" uri="ssl://0.0.0.0:61617?transport.needClientAuth=false"/> </transportConnectors>
Note
To enable mutual authentication, set
transport.needClientAuth=true
, and import the IDM server certificate into the ActiveMQ truststore (conf/broker.ts
).
Delete the existing self-signed server certificate from the ActiveMQ keystore and truststore:
keytool \ -delete \ -keystore /path/to/activeMQ/conf/broker.ts \ -alias broker-localhost
Enter keystore password:
password keytool \ -delete \ -keystore /path/to/activeMQ/conf/broker.ks \ -alias broker-localhost
Enter keystore password:
password
Generate a new self-signed server certificate for ActiveMQ:
keytool \ -genkey \ -keyalg RSA \ -alias broker-localhost \ -keystore /path/to/activeMQ/conf/broker.ks \ -storepass password \ -validity 360 \ -keysize 2048
Important
The
CN
in the generated self-signed certificate must match the hostname that you specify in the IDM JMS provider URL. If you are usinglocalhost
to connect to the broker, you must specifylocalhost
when keytool prompts you for thefirst and last name
. If theCN
is not the same as the hostname, the server certificate validation will fail.Export the ActiveMQ server certificate:
keytool \ -export \ -alias broker-localhost \ -file broker-localhost.key \ -keystore /path/to/activeMQ/conf/broker.ks
Enter keystore password:
password
Certificate stored in file <broker-localhost.key>
Import the ActiveMQ server certificate into the IDM truststore:
keytool \ -import \ -alias activemq \ -keystore /path/to/openidm/security/truststore \ -file broker-localhost.key
Enter keystore password:
changeit
Owner: CN=localhost, OU=Unknown, O=example.com, L=Unknown, ST=Unknown, C=Unknown Issuer: CN=localhost, OU=Unknown, O=example.com, L=Unknown, ST=Unknown, C=Unknown ... Trust this certificate? [no]:
yes
Certificate was added to keystore
Configure a Secure Port for JMS Messages
Edit /path/to/openidm/samples/audit-jms/conf/audit.json
, as follows:
"java.naming.provider.url" : "ssl://localhost:61617?daemon=true"
Start the ActiveMQ Broker and IDM
With the appropriate bundles in the /path/to/openidm/bundle/
directory, you can start the ActiveMQ message broker, then start IDM with the configuration for this sample.
Navigate to the directory where you unpacked the ActiveMQ binary and run the following command to start the ActiveMQ broker:
cd ~/Downloads/apache-activemq-5.16.1 bin/activemq start
INFO: Loading '/path/to/Downloads/apache-activemq-5.16.1/bin/env' INFO: Using java '/usr/bin/java' INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get details INFO: pidfile created : '/path/to/Downloads/apache-activemq-5.16.1/data/activemq.pid' (pid '69627')
Start IDM with the sample configuration:
cd /path/to/openidm/ ./startup.sh -p samples/audit-jms
Go to the ActiveMQ Console at
http://localhost:8161/admin/topics.jsp
, and verify audit messages are being created and sent to theforgerock.idm.audit
audit topic.
Note
If you see the following error in the OSGi console, make sure that you have installed all the required dependencies and that you have started the ActiveMQ broker.
SEVERE: Unable to create JmsAuditEventHandler 'jms': null
Configure and Use a JMS Consumer Application
To take advantage of the Apache ActiveMQ event broker, the JMS audit sample includes a Java consumer in the following directory: /path/to/openidm/samples/audit-jms/consumer/
Assuming you have Apache Maven installed on the local system, you can compile that sample consumer with the following commands:
cd /path/to/openidm/samples/audit-jms/consumer/
mvn clean install
When the build process is complete, you'll see a BUILD SUCCESS
message:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 22.852 s
[INFO] Finished at: 2017-02-17T17:21:35+02:00
[INFO] Final Memory: 18M/148M
[INFO] ------------------------------------------------------------------------
Note
You might see [WARNING]
messages during the build. As long as the messages end with BUILD SUCCESS
, you can proceed with the JMS consumer application.
When the consumer is compiled, run the following command in the same directory to output audit messages related to IDM actions:
mvn \ exec:java \ -Dexec.mainClass="consumer.src.main.java.SimpleConsumer" \ -Dexec.args="tcp://localhost:61616"
[INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building SimpleConsumer 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- exec-maven-plugin:1.5.0:java (default-cli) @ SimpleConsumer --- Downloading: https://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/... Downloaded: https://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/... Downloading: https://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/... Downloaded: https://repo.maven.apache.org/maven2/org/apache/commons/commons-exec/... Connection factory=org.apache.activemq.ActiveMQConnectionFactory READY, listening for messages. (Press 'Enter' to exit)
Look for the message READY, listening for messages
.
If you've configured ActiveMQ on a secure port, run this command:
MAVEN_OPTS="-Djavax.net.ssl.trustStore=/path/to/openidm/security/truststore" \
mvn \
exec:java \
-Dexec.mainClass="consumer.src.main.java.SimpleConsumer" \
-Dexec.args="ssl://localhost:61617?daemon=true"
Try some actions on IDM, either in a different console or in the Admin UI. Watch the output in the SimpleConsumer
console. For example, you might see output similar to the following when you run a reconciliation on the data in this sample:
{ "auditTopic": "recon", "event" :{ "transactionId": "f3e108a9-eb75-4ec8-96c5-9dc2f5137d51-176", "timestamp": "2017-02-17T15:25:34.899Z", "eventName": "recon", "userId": "openidm-admin", "exception": null, "linkQualifier": null, "mapping": "systemCsvfileAccounts_managedUser", "message": "SOURCE_IGNORED: 0 UNASSIGNED: 0 AMBIGUOUS: 0 CONFIRMED: ...", "messageDetail": { "_id": "f3e108a9-eb75-4ec8-96c5-9dc2f5137d51-176", "mapping": "systemCsvfileAccounts_managedUser", "state": "SUCCESS", "stage": "COMPLETED_SUCCESS", "stageDescription": "reconciliation completed.", "progress": { "source": { "existing": { "processed": "2", "total": "2" } } } } } }