A few days ago I published the article Liferay Portal Security Audit with the aim of explaining what the system is and how it works of Liferay's Security Audit, and to understand how to extend its functionality. As an ultra-bonus, all the source code developed is publicly available on my GitHub repository, liferay-portal-security-audit.
Figure 1 shows the macro-architecture of Liferay Portal Security Audit. In the article, we discussed how to implement the two components at the base of the framework: the Audit Router and the Audit Message Processors.
In this article, I would like to show you how simple it is to create a new Audit Message Processor component that receives audit messages and forwards them (possibly after processing) to a message-oriented middleware system.
Figure 1 - Liferay Portal Security Audit Architecture Macro
I decided to use AMQP as a communication protocol between client and broker. The Advanced Message Queuing Protocol (AMQP) protocol was developed to solve interoperability problems between different messaging-oriented middleware products.
AMQP (international standard approved by ISO and IEC as ISO/IEC 19464: 2014) is an efficient and reliable wire-level messaging protocol that can be used to create multi-platform and reliable messaging applications.
This protocol serves a simple purpose: to define the mechanisms for the secure, reliable, and efficient transmission of messages between two parties. The messages themselves are encoded using a portable data representation that allows heterogeneous senders and recipients to exchange structured business messages with absolute fidelity.
The new Audit Message Processor we are going to implement will use AMQP as a protocol for sending audit messages to a specific queue hosted by a messaging broker that supports this type of protocol. The broker I have decided to use for this example is RabbitMQ. In Figure 2 the case described above is illustrated.
Figure 2 - Audit Message Processor that processes and sends audit messages to an AMQP message broker
RabbitMQ is the most widespread open source message broker that implements the AMQP protocol. Here, for convenience purposes we will use CloudAMQP, RabbitMQ servers managed in the cloud. Figure 3 shows the flow of the publication of audit messages from the Liferay Portal to the CloudAMQP message broker. The messages in the queue can then be consumed.
Figure 3 - Sending messages via AMQP using the CloudAMQP service
1. How to Implement the Audit Message Processor
In the Audit Service ecosystem, the Audit Message Processor is the component responsible for processing the audit messages received by the Audit Router.
We remind you that the Audit Service system can have one or more Audit Message Processors (but also zero, as in the case of the Community Edition of Liferay). It is possible to configure two types of message processors: global processors and processors for certain types of events; in this way, we are in a position to differentiate the place where to store the actions according to their type.
Our Audit Message Processor we are going to implement will be an OSGi component that we will call CloudAMQP Audit Message Processor and which will have to implement the Audit Message Processor interface.
This interface declares the only method: void process (AuditMessagge auditMessage), called by the Audit Router.
Before going to implement the new Audit Message Processor, let's see what the features are:
Global type. Defined through the property
eventTypes
of the@components
annotation, with the OSGi set to the value*
(star or asterisk).Receives audit messages that it processes and then sends to the messaging broker via the AMQP protocol.
The parameters necessary for communication with CloudAMQP must be read from the OSGi configuration.
Table 1 shows the main characteristics of the message processor we are going to implement. The OSGi configuration associated with the new component is defined via the CloudAMQPAuditMessageProcessorConfiguration interface available as the source code of the liferay-portal-security-audit project on GitHub.
Feature/OSGi configuration |
Description |
Tipo Globale | Global Audit Message Processor. All audit messages pass through this message processor. |
Enabled | Allows you to enable or disable the message processor. The default value is set to false. |
Server Address | IP address or FQDN of the CloudAMQP server. |
User Name | Username to access CloudAMQP services. |
Password | Password to access CloudAMQP services. |
Queue Name | Name of the queue defined in CloudAMQP. |
Table 1 - Characteristics of the CloudAMQP Message Processor
In order to send the audit messages to the message broker through the AMQP protocol, we need a library that facilitates the task. RabbitMQ offers the most disparate platforms, languages, and libraries that implement the client that speaks in AMQP. Among the supported languages there is also Java, moreover, the latest versions are also OSGi compliant.
The steps necessary to complete the implementation of the message processor are:
Configuring the AMQP client as a Gradle dependency (client version used in 5.1.2).
Implementation of the void process method (AuditMessage auditmessage) which:
Verifies that the message processor is enabled.
Turns the audit message into JSON format and then into bytes (as requested by AMQP).
Creates a connection to CloudAMQP using the parameters read from the OSGi configuration.
Creates the communication channel.
Queues setup (whose name is in the OSGi configuration).
Publication of the audit message.
Closing of the communication channel.
Termination of the connection.
Code 1 shows part of the build.gradle file to include the AMQP client dependency. In this case, the dependency must also be included in the final bundle, here is the reason for using compileInclude in Gradle dependencies.
dependencies {
compileInclude group: "com.rabbitmq", name: "amqp-client", version: "5.1.2"
...
}
Code 1 - Inclusion of the AMQP client dependency
Instead, Code 2 shows the core part of the implementation of the process method. The complete code of the CloudAMQPAuditMessageProcessor is available as the source code of the liferay-portal-security-audit project on GitHub.
try {
if (_log.isDebugEnabled()) {
_log.debug("Try to connect " + _buildAMQPURI() + "...");
}
ConnectionFactory factory = new ConnectionFactory();
factory.setUri(_buildAMQPURI());
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(
_cloudAMQPAuditMessageProcessorConfiguration.queueName(),
durable, exclusive, autoDelete, null);
channel.basicPublish("",
_cloudAMQPAuditMessageProcessorConfiguration.queueName(),
null,
auditMessage.toJSONObject().toString().getBytes("UTF-8"));
channel.close();
connection.close();
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(
"Send Message Audit to Cloud AMQP Queue failed.", e);
}
}
}
Code 2 - Implementation of the process method
2. Deploy of the Audit Message Processor
The Liferay Portal Security Audit project is organized as shown in Table 2.
Name of the module | Description of the module |
portal-security-audit-capture-events | This module contains components that capture portal events such as AuthFailure. These components trace events by sending them to message processors through the Audit Router. |
portal-security-audit-router | This module contains the Standard Audit router component that implements the Audit Router interface. |
portal-security-message-processor | This module contains the message processors: Dummy Audit Message Processor, Login Failure Message Processor, and CloudAMQP Audit Message Processor. |
Table 2 - New modules added to the Liferay Portal Security Audit system
The CloudAMQP Audit Message Processor is part of the portal-security-message-processor module that can be installed on both the Community Edition and the Liferay DXP. In the case of installation on the DXP, you only need to install the portal-security-message-processor bundle (in.dontesta.labs.liferay.portal.security.audit.message.processor.jar), on the contrary, on the Community Edition, you need to install the three bundles of the three modules.
To proceed with the deployment, follow the steps indicated below:
$ git clone https://github.com/amusarra/liferay-portal-security-audit.git
$ cd liferay-portal-security-audit
$ ./gradlew clean deploy
$ cp ../bundles/osgi/modules/*.jar $LIFERAY_HOME/deploy/
In the my case, $LIFERAY_HOME is set on this directory: /opt/liferay-ce-portal-7.0-ga5
Verify the correct deployment of the three bundles via the Liferay log file or through the Gogo Shell using the lb command, making sure that the status is Active.
$ telnet localhost 11311
g! lb|grep Audit
342|Active | 10|Liferay Portal Security Audit API (2.0.2)
343|Active | 10|Liferay Portal Security Audit Wiring (2.0.4)
584|Active | 10|Liferay Portal Security Audit Capture Events (1.0.0)
586|Active | 10|Liferay Portal Security Audit Message Processor (1.0.0)
587|Active | 10|Liferay Portal Security Audit Router (1.0.0)
3. Configuration of the Audit Message Processor
Once the CloudAMQP Audit Message Processor bundle has been installed, you must configure the connection parameters to your CloudAMQP instance. Figure 4 shows an example of the configuration.
Figure 4 - Configuration of the CloudAMQP Audit Message Processor
Remember that in order for the message processor to work (capture audit messages), the Audit system (also from the Control Panel) must be enabled, as well as itself.
4. The CloudAMQP Audit Message Processor in Action
At this point, we need to test the new Audit Message Processor. When checking the events of LOGIN, LOGIN_FAILURE, etc., on the Liferay log we can verify entries that indicate that the audit messages have been published to CloudAMQP.
18:52:10,827 INFO [liferay/audit-1][CloudAMQPAuditMessageProcessor:125] Message Audit processed and published on liferay_audit_queue Cloud AMQP queue.
Details {{product=RabbitMQ, copyright=Copyright (c) 2007-2017
Pivotal Software, Inc.,
capabilities={exchange_exchange_bindings=true, connection.blocked=true,
authentication_failure_close=true, basic.nack=true,
publisher_confirms=true, consumer_cancel_notify=true},
information=Licensed under the MPL. See http://www.rabbitmq.com/,
version=5.1.2, platform=Java}}
It is possible to verify the correct publication of the audit messages by consulting the CloudAMQP console. The following figures show a series of screenshots that show the correct functioning of the Audit Message Processor.
Figure 5 - Global status of the code
Figure 6 - List and details of the queues
Figure 7 - Reading messages from the queue
Summary
With this article, I tried to explain with simplicity how, thanks to the Liferay framework Security Audit, it is easy to create an Audit Message Processor that publishes the audit messages to a message broker using the AMQP protocol. Moreover, with this article, we have seen how it is also easy to integrate Liferay with a messaging system based on the AMQP protocol.
I hope I was clear in the show and that it captured your interest in the subject; if so, you could return the favor by sharing the article on social network channels or others, what I wrote could also be useful to other people.
Feel free to contact me if you have any questions or need help. I'm @antonio_musarra on Twitter and amusarra on LinkedIn. I'll even wait for you on my Antonio Musarra's Blog.