Use the UltraESB as a Security Gateway for HTTP/S, REST, SOAP, Hessian, Text etc

DZone 's Guide to

Use the UltraESB as a Security Gateway for HTTP/S, REST, SOAP, Hessian, Text etc

· Integration Zone ·
Free Resource

This article explains how the UltraESB could be used as a HTTP/S or SOAP Security gateway, to front internally deployed services of an organization in a SOA. The UltraESB allows SSL termination, WS-Security validation/termination, HTTP Basic/Digest authentication enforcement, Client SSL certificate validation etc, from a security point of view. Additionally it provides validation and transformation capabilities - and supports secure XML processing which safeguards the infrastructure from XML based attacks.


The UltraESB is a high-performance ESB that uses Java NIO and Operating System support for Zero-Copy [1] when available - to provide extreme performance whilst ensuring simplicity in use. Currently supporting transports such as HTTP/S, JMS, SFTP, FTP/S, Email (POP3, IMAP, SMTP), Files, TCP, MLLP/S with messages of SOAP, XML, Text, Binary, Hessian, Map, HL7 etc it provides a simple to use but powerful platform to build a Service Oriented Architecture (SOA) platform for an organization. It is available for unlimited and perpetual use free of charge, with the source code available for partners. Configuration of the UltraESB is via a Spring configuration file and mediation via Java, Spring or any JSR 233 scripting languages such as Javascript, Groovy, Ruby etc. without having to learn any new DSL or XML configuration language. When Java snippets or Scripting languages are used for mediation, the source code can be specified inline or externally within the configurtion, and is dynamically compiled into bytecode at runtime. Thus there is nothing to compile or bundle etc when deploying services to the UltraESB - everything is just specified as configuration!

Proxy Services and Why they are needed

A Proxy Service defines an endpoint exposed over the ESB [“P”], that accepts messages from external or internal clients, and forwards these requests between one or more back-end service implementations.
Using a Proxy exposed on the ESB instead of directly exposing the service implementations has many advantages.

  • For example a proxy service can prevent any client or application from being tied to the individual service endpoint URLs originally exposed by the service implementation. This allows the service implementations to be migrated independently to updated versions or URLs etc, without disrupting production users. This also allows multiple service implementations to be used in a Load balanced or Fail over group, and to take down individual endpoints off-line for maintenance purposes, while continuing to serve users with other instances.

  • Exposing each service over the ESB allows security and validations to be performed easily and consistently. The Proxy service endpoint maybe used to perform HTTP Basic or Digest authentication, SSL termination, 2-way SSL enforcement and optional validation of client certificate DN or WS-Security validation or Termination. Additionally, messages maybe validated against a schema or transformed using an XSLT or other means, before forwarding to the service implementations. Moving these aspects to the ESB simplifies the internal service implementations saving time and testing effort, and allows easy maintenance via configuration - without any changes required on the service implementations thereafter. For example, one could write a SOAP service implementation in PHP, but use the WS-Security capabilities of the ESB.

Unsecured Proxy Services

An unsecured proxy maybe typically hosted over HTTP as a REST, SOAP, XML or any other type - such as Hessian etc. Definition of such a proxy is trivial and consists of a definition similar to the following (See samples # 101, 201 etc for more details)

<u:proxy id="soap-proxy">
<u:transport id="http-8280"/>
<u:address type="response"/>

An UltraESB configuration is a Spring configuration - with custom extensions for Proxy service definitions. Each Proxy service is identified by an ID, which maps the Proxy to a URL pattern such as “/service/<proxy-id>”. Of course, the default context path, or the desired service name is configurable. The transport ID refers to one or more transport listener definitions - which are standard Spring beans similar to the following definition.

<bean id="http-8280" class="org.adroitlogic.ultraesb.transport.http.HttpNIOListener">
<constructor-arg ref="fileCache"/>
<property name="port" value="8280"/>

The port used, the default socket timeout, or the interface used for accepting connections on a multi-IP system etc, and many more advanced options are fully configurable and defaults to production-ready settings for simplicity.

Endpoints - Round Robin, Failover, Random, Weighted etc

The “Target” of a Proxy service defines the destination for messages. In the above example, incoming messages are destined to the SimpleStockQuoteService endpoint, while responses received are sent back to the original client - i.e. inDestination and outDestination. The destination can define a single endpoint, or multiple endpoints as load balanced round-robin, weighted, random or fail over groups (See sample # 601 for more examples).

Detection of timeouts, failures and unexpected failure responses and turning off endpoints

Although some ESB's limit fail-over only to connection attempt failures at a network level, the UltraESB optionally allows response messages to be validated - for example on transport headers, or response body. Thus it is possible to take out failed or timed out endpoints as well as an endpoint that returns invalid/unexpected responses from a group. Temporary failures puts endpoints into retries, and exceeding a retry limit, or a critical fault (such as non-acceptance of connections) puts an endpoint into suspension. Suspended or timed out endpoints are periodically checked for re-emergence or valid operation according to the default or specified configuration parameters.

Messages maybe sent to endpoints over a different transport than the one that received the message. Thus HTTP/S to JMS, SFTP to Files, HL7/MLLP to SOAP, Email to JMS or any transport to any other transport or message format is possible - but is outside the scope of this article.

Mediation of messages with Sequences - including support for JTA

The messages received at a proxy service, and responses received from the backend response maybe mediated in a myriad of ways using multiple approaches. The UltraESB does not define a new DSL or a XML based language for its users to learn - but instead allows them to mediate with the language they are already most accustomed to. The UltraESB API is mainly limited to two classes, and maybe mediated with Java code snippets, Java classes, Spring beans, or any JSR 233 scripting language (e.g. Groovy, Javascript, Ruby etc) scriptlets or files. (See below for sample Sequence definitions)The API allows for easy initiation, commit or rollback of JTA transactions - so that any mediation using JTA aware resources are automatically bound to the transactions (See sample #105 on how JTA has been used with HTTP and JDBC). It also supports suspension and resumption of transactions - and thus a message maybe sent to a remote service, and the transaction suspended until the response is received to decide on the commit or rollback decision.

1. HTTP Basic and Digest authentication

HTTP authentication is defined at the transport listener level, and it is possible to have multiple listener instances over multiple ports within the UltraESB. To use Basic authentication or Digest authentication a configuration similar to the following is used, where requests are filtered. Note that the authentication credentials provider is a standard Spring Security definition - and thus allows authentication information to be used against a Database, in-memory store, custom provider or any other Spring security supported provider.

<bean id="http-8280" class="org.adroitlogic.ultraesb.transport.http.HttpNIOListener">
<constructor-arg ref="fileCache"/>
<property name="port" value="8280"/>
<property name="requestFilters">
<bean class="org.adroitlogic.ultraesb.transport.http.auth.BasicAuthenticationFilter">
<property name="realmName" value="adroitlogic"/>

<s:password-encoder hash="md5"/>
<s:user name="asankha" password="abac6d7582d9ab52c629f7490fd3eb2f" authorities="ROLE_ADMIN, ROLE_USER"/>

In this example, we us an in-memory authentication provider, with hashed passwords. When using Digest authentication the original password should however be available to the ESB (See sample # 103 for an example) - although it maybe specified as an encrypted String using Jasypt [2].

2. Securing services with WS-Security

A WS-Security secured Proxy service maybe exposed easily over the UltraESB, without spending loads of time learning about and writing WS-Policy and other configurations. To use WS-Security with the UltraESB, usually required the definition of the WSSecurityManager bean to the configuration as shown below.

<bean id="wssecMgr" class="org.adroitlogic.soapbox.WSSecurityManager">
<constructor-arg value="samples/conf/keys/ws-sec-keystore.jks"/>
<constructor-arg value="password"/>
<entry key="alice" value="password"/>
<entry key="bob" value="password"/>

The WSSecurityManager defines the identity and trust keystores, and the passwords to access the credentials. Any passwords stored on the UltraESB configuration can easily be encrypted using Jasypt as per the article [2]. The sample # 204 shows a typical WS-Security termination scenario using Timestamps, Signatures and Encryption with UsernameToken authentication for which the complete configuration is as follows:

<u:proxy id="ws-sec-proxy">
<u:transport id="http-8280">
<u:property name="wsdlURL" value="file:samples/resources/SimpleStockQuoteService.wsdl"/>
try {
WSSecurityManager wssecMgr = Mediation.getWSSecurityManager();
wssecMgr.verifyTimestampedEncryptedAndSignedMessage(msg, true);
} catch (Exception e) {
Mediation.setPayloadToSOAP11Fault(msg, null, "Security validation failed", null);
Mediation.sendResponse(msg, 500);
Mediation.getWSSecurityManager().timestampSignAndEncryptMessage(msg, "bob", "alice");
<u:address type="response"/>

When securing a message with WS-Security, the identity of the signer (e.g. “bob”) and the encryption identity (e.g. “alice”) may be specified. The API keeps the configuration extremly simple - although it results in a full WS-Security definition. The various advanced security aspects such as algorithms and key sizes etc, maybe adjusted easily via the API [3].
The sample #204 additionally shows how unsecured requests - such as those originating from within an organization - maybe enriched with the organizational or Partner WS-Security standards when sent out. Of course the API's make it trivial to only use a subset of the WS-Security features - for example, just Timestamps and Signatures without Encryption (E.g. when requests are made over SSL for performance reasons)

3. SSL Termination and 2-way SSL authentication of clients

The UltraESB SSL transport lister allows the specification of identity and trust keystores, that allows proper use of SSL between clients and the proxy service.

<bean id="https-8443" class="org.adroitlogic.ultraesb.transport.http.HttpsNIOListener">
<constructor-arg ref="fileCache"/>
<property name="sslVerifyClient" value="optional"/>
<property name="identityStorePath" value="conf/keys/identity.jks"/>
<property name="identityKeyPassword" value="password"/>
<property name="identityStorePassword" value="password"/>
<property name="trustStorePath" value="conf/keys/identity.jks"/>
<property name="trustStorePassword" value="password"/>
<property name="port" value="8443"/>

The “sslVerifyClient” property will specify if client authentication (i.e. 2-way SSL) is required, optional or not used. For testing purposes the property “nonProductionNoRemoteCertValidation” disables remote certificate validation - although it should not be used in production systems. When making requests over SSL against remote services, the UltraESB transport sender allows a similar specification of properties for configuration - including how hostname verification is performed. For testing purposes, all validation could again be disabled completely.
By using a custom trust store that holds CA certificates trusted by the organization and its own CA certificates, it is easy to ensure that only legitimate users or business partners are allowed to access the services. Optionally, the client certificate properties (e.g. the DN is available as msg.getMessageProperty("ultra.https.client_dn")) maybe used during mediation to decide on the security levels or priorities etc during mediation.

Getting Started with the UltraESB

The complete UltraESB distribution is ~25MB in size, and includes ready-to-run samples, mock services and client tools to test all features described above within minutes. The ToolBox [4] allows one to make requests using no security, SSL/2-way SSL, as well as use pre-defined WS-Security requests for testing or load testing.

Read more about the UltraESB at http://adroitlogic.org

Performance Benchmark

Recently AdroitLogic published results of the 4th round of ESB performance testing, and has publicly made available all resources to allow end-users to easily compare the UltraESB with other options - on local hardware or the Amazon EC2 [5]. WS-Security performance in particular is exceptional with over a 3X TPS over alternatives using the standard WSS4J based implementations underneath.


[1] http://adroitlogic.org/samples-articles-and-tutorials/16-articles/13-non-blocking-and-zero-copy-proxying.html
[2] http://adroitlogic.org/samples-articles-and-tutorials/15-tutorials/24-securing-the-ultraesb-configuration.html
[3] http://adroitlogic.org/samples-articles-and-tutorials/16-articles/51-reference-guide-mediation-and-configuration.html
[4] http://adroitlogic.org/samples-articles-and-tutorials/15-tutorials/18-getting-started-with-the-adroitlogic-toolbox-for-the-ultraesb.html
[5] http://adroitlogic.org/samples-articles-and-tutorials/15-tutorials/48-esb-performance.html

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}