7.2. Securing the Web Services Proxy
Overview
This section explains how to enable SSL/TLS security on the Camel CXF endpoint, which acts as a proxy for the real Web service. Assuming that you already have the X.509 certificates available, all that is required is to add a block of configuration data to the Spring configuration file (where the configuration data is contained in a
httpj:engine-factory
element). There is just one slightly subtle aspect to this, however: you need to understand how the Camel CXF endpoint gets associated with the SSL/TLS configuration details.
Implicit configuration
A WS endpoint can be configured by creating the endpoint in Spring and then configuring SSL/TLS properties on its Jetty container. The configuration can be somewhat confusing, however, for the following reason: the Jetty container (which is configured by a
httpj:engine-factory
element in Spring) does not explicitly reference the WS endpoints it contains and the WS endpoints do not explicitly reference the Jetty container either. The connection between the Jetty container and its contained endpoints is established implicitly, in that they are both configured to use the same TCP port, as illustrated by Figure 7.2, “WS Endpoint Implicitly Configured by httpj:engine-factory Element”.
Figure 7.2. WS Endpoint Implicitly Configured by httpj:engine-factory Element
The connection between the Web service endpoint and the
httpj:engine-factory
element is established as follows:
- The Spring container loads and parses the file containing the
httpj:engine-factory
element. - When the
httpj:engine-factory
bean is created, a corresponding entry is created in the registry, storing a reference to the bean. Thehttpj:engine-factory
bean is also used to initialize a Jetty container that listens on the specified TCP port. - When the WS endpoint is created, it scans the registry to see if it can find a
httpj:engine-factory
bean with the same TCP port as the TCP port in the endpoint's address URL. - If one of the beans matches the endpoint's TCP port, the WS endpoint installs itself into the corresponding Jetty container. If the Jetty container has SSL/TLS enabled, the WS endpoint shares those security settings.
Steps to add SSL/TLS security to the Jetty container
To add SSL/TLS security to the Jetty container, thereby securing the WS proxy endpoint, perform the following steps:
Add certificates to the bundle resources
The certificates used in this demonstration are taken from a sample in the Apache CXF 3.1.5.redhat-630xxx product. If you install the standalone version of Apache CXF (available in the
InstallDir/extras/
directory), you will find the sample certificates in the CXFInstallDir/samples/wsdl_first_https/src/main/config
directory.
Copy the
clientKeystore.jks
and serviceKeystore.jks
keystores from the CXFInstallDir/samples/wsdl_first_https/src/main/config
directory to the CamelInstallDir/examples/camel-example-cxf-proxy/src/main/resources/certs
directory (you must first create the certs
sub-directory).
Modify POM to switch off resource filtering
Including the certificates directly in the bundle as resource is the most convenient way to deploy them. But when you deploy certificates as resources in a Maven project, you must remember to disable Maven resource filtering, which corrupts binary files.
To disable filtering of
.jks
files in Maven, open the project POM file, CamelInstallDir/examples/camel-example-cxf-proxy/pom.xml
, with a text editor and add the following resources
element as a child of the build
element:
<?xml version="1.0" encoding="UTF-8"?> ... <project ...> ... <build> <plugins> ... </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <excludes> <exclude>**/*.jks</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <includes> <include>**/*.jks</include> </includes> </resource> </resources> </build> </project>
Instantiate the CXF Bus
You should instantiate the CXF bus explicitly in the Spring XML (this ensures that it will be available to the Jetty container, which is instantiated by the
httpj:engine-factory
element in the next step). Edit the camel-config.xml
file in the src/main/resources/META-INF/spring
directory, adding the cxfcore:bus
element as a child of the beans
element, as follows:
<beans ... >
...
<cxfcore:bus/>
...
</beans>
Note
The
cxfcore:
namespace prefix will be defined in a later step.
Add the httpj:engine-factory element to Spring configuration
To configure the Jetty container that listens on TCP port 9080 to use SSL/TLS security, edit the
camel-config.xml
file in the src/main/resources/META-INF/spring
directory, adding the httpj:engine-factory
element as shown in Example 7.2, “httpj:engine-factory Element with SSL/TLS Enabled”.
In this example, the
required
attribute of the sec:clientAuthentication
element is set to false
, which means that a connecting client is not required to present an X.509 certificate to the server during the SSL/TLS handshake (although it may do so, if it has such a certificate).
Example 7.2. httpj:engine-factory Element with SSL/TLS Enabled
<beans ... > ... <httpj:engine-factory bus="cxf"> <httpj:engine port="${proxy.port}"> <httpj:tlsServerParameters secureSocketProtocol="TLSv1"> <sec:keyManagers keyPassword="skpass"> <sec:keyStore resource="certs/serviceKeystore.jks" password="sspass" type="JKS"/> </sec:keyManagers> <sec:trustManagers> <sec:keyStore resource="certs/serviceKeystore.jks" password="sspass" type="JKS"/> </sec:trustManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> <sec:clientAuthentication want="true" required="false"/> </httpj:tlsServerParameters> </httpj:engine> </httpj:engine-factory> </beans>
Important
You must set
secureSocketProtocol
to TLSv1
on the server side, in order to protect against the Poodle vulnerability (CVE-2014-3566)
Define the cxfcore:, sec: and httpj: prefixes
Define the
cxfcore:
, sec:
and httpj:
namespace prefixes, which appear in the definitions of the cxfcore:bus
element and the httpj:engine-factory
element, by adding the following highlighted lines to the beans
element in the camel-config.xml
file:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring" xmlns:cxf="http://camel.apache.org/schema/cxf" xmlns:context="http://www.springframework.org/schema/context" xmlns:cxfcore="http://cxf.apache.org/core" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd ">
Note
It is essential to specify the locations of the
http://cxf.apache.org/configuration/security
schema and the http://cxf.apache.org/transports/http-jetty/configuration
schema in the xsi:schemaLocation
attribute. These will not automatically be provided by the OSGi container.
Modify proxy address URL to use HTTPS
The proxy endpoint at the start of the Apache Camel route is configured by the
cxf:cxfEndpoint
element in the camel-config.xml
file. By default, this proxy endpoint is configured to use the HTTP protocol. You must modify the address URL to use the secure HTTPS protocol instead, however. In the camel-config.xml
file, edit the address attribute of the cxf:cxfEndpoint
element, replacing the http:
prefix by the https:
prefix, as shown in the following fragment:
<beans ...>
...
<cxf:cxfEndpoint id="reportIncident"
address="https://localhost:${proxy.port}/camel-example-cxf-proxy/webservices/incident"
endpointName="s:ReportIncidentEndpoint"
serviceName="s:ReportIncidentEndpointService"
wsdlURL="etc/report_incident.wsdl"
xmlns:s="http://reportincident.example.camel.apache.org"/>
...
</beans>
Notice also that the address URL is configured to use the TCP port,
${proxy.port}
(which has the value 9080
by default). This TCP port value is the same as the value set for the Jetty container (configured by the http:engine-factory
element), thus ensuring that this endpoint is deployed into the Jetty container. The attributes of the cxf:cxfEndpoint
specify the WSDL addressing details as described in the section called “WSDL addressing details”:
-
serviceName
- Specifies the WSDL service name.
-
endpointName
- Specifies the WSDL port name.
-
address
- Specifies the address URL of the proxy Web service.