Chapter 5. Securing the Camel Jetty Component
Abstract
5.1. Enabling SSL/TLS Security
Overview
This section explains how to enable SSL/TLS security on the Apache Camel Jetty component, which is used to create a HTTPS Web server. The key step is to customize the Jetty component by setting the
sslSocketConnectorProperties
property, which configures SSL/TLS. You must also change the protocol scheme on the Jetty URI from http
to https
.
Tutorial steps
To configure SSL/TLS security for a Camel Jetty endpoint deployed in the OSGi container, perform the following steps:
Generate a Maven project
The
maven-archetype-quickstart
archetype creates a generic Maven project, which you can then customize for whatever purpose you like. To generate a Maven project with the coordinates, org.jbossfuse.example:jetty-security
, enter the following command:
mvn archetype:create -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=org.jbossfuse.example -DartifactId=jetty-security
The result of this command is a directory,
ProjectDir/jetty-security
, containing the files for the generated project.
Note
Be careful not to choose a group ID for your artifact that clashes with the group ID of an existing product! This could lead to clashes between your project's packages and the packages from the existing product (because the group ID is typically used as the root of a project's Java package names).
Customize the POM file
You must customize the POM file in order to generate an OSGi bundle. Follow the POM customization steps described in section "Generating a Bundle Project" in "Deploying into the Container".
Alternatively, edit the
jetty-security/pom.xml
file and replace its contents with the following XML code:
<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"> <modelVersion>4.0.0</modelVersion> <groupId>org.jbossfuse.example</groupId> <artifactId>jetty-security</artifactId> <version>1.0-SNAPSHOT</version> <packaging>bundle</packaging> <name>jetty-security</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <defaultGoal>install</defaultGoal> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>2.3.7</version> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName> <Import-Package>*</Import-Package> </instructions> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build> </project>
Install sample keystore files
The certificates used in this demonstration are taken from a sample in the Apache CXF 3.0.4.redhat-620133 distribution, which is included in the
InstallDir/extras
directory. Using a standard archive utility, expand the CXF archive file and extract the contents to a convenient location on your filesystem. You will find the sample certificates in the CXFInstallDir/samples/wsdl_first_https/src/main/config
directory.
Copy the
clientKeystore.jks
certificate and the serviceKeystore.jks
certificate from the CXFInstallDir/samples/wsdl_first_https/src/main/config
directory to the EsbInstallDir/etc/certs
directory (where you will need to create the etc/certs
sub-directory). After copying, you should have the following directory structure under EsbInstallDir/etc/
:
EsbInstallDir/etc/ | \--certs/ | \--clientKeystore.jks serviceKeystore.jks
Where
clientKeystore.jks
, and serviceKeystore.jks
are the keystores that are used in this demonstration.
Warning
The demonstration key store and trust sture are provided for testing purposes only. Do not deploy these certificates in a production system. To set up a genuinely secure SSL/TLS system, you must generate custom certificates, as described in Appendix A, Managing Certificates.
Configure Jetty with SSL/TLS
The Jetty Web server is created by defining a Jetty endpoint at the start of an Apache Camel route. The route is then responsible for processing the incoming HTTP request and generating a reply. The current example simply sends back a small HTML page in the reply. For a more realistic application, you would typically process the incoming message using a bean, which accesses the message through the Java servlet API.
Create the following directory to hold the Spring configuration files:
ProjectDir/jetty-security/src/main/resources/META-INF/spring
In the
spring
directory that you just created, use your favourite text editor to create the file, jetty-spring.xml
, containing the following XML configuration:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.4.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <bean id="jetty" class="org.apache.camel.component.jetty8.JettyHttpComponent8"> <property name="sslContextParameters" ref="sslContextParameters" /> </bean> <sslContextParameters id="sslContextParameters" xmlns="http://camel.apache.org/schema/spring"> <secureSocketProtocols> <!-- Do NOT enable SSLv3 (POODLE vulnerability) --> <secureSocketProtocol>TLSv1</secureSocketProtocol> <secureSocketProtocol>TLSv1.1</secureSocketProtocol> <secureSocketProtocol>TLSv1.2</secureSocketProtocol> </secureSocketProtocols> <keyManagers keyPassword="skpass"> <keyStore resource="etc/certs/serviceKeystore.jks" password="sspass"/> </keyManagers> <trustManagers> <keyStore resource="etc/certs/serviceKeystore.jks" password="sspass"/> </trustManagers> </sslContextParameters> <camelContext trace="true" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="jetty:https://0.0.0.0:8282/services?matchOnUriPrefix=true"/> <transform> <constant><html><body>Hello from Fuse ESB server</body></html></constant> </transform> </route> </camelContext> </beans>
The
jetty
bean defines a new instance of the Apache Camel Jetty component, overriding the default component defined in the camel-jetty
JAR file. This Jetty component is configured using the sslContextParameters
element, as follows:
secureSocketProtocols
- Explicitly lists the SSL/TLS protocols supported by the Jetty server.ImportantThis configuration explicitly disables the SSLv3 protocol, in order to safeguard against the Poodle vulnerability (CVE-2014-3566). For more details, see Disabling SSLv3 in JBoss Fuse 6.x and JBoss A-MQ 6.x.
keyManagers/@keyPassword
- The password that decrypts the private key stored in the keystore (usually having the same value as
password
). keyManagers/keyStore/@resource
- The location of the Java keystore file (in JKS format) containing the Jetty server's own X.509 certificate and private key. This location is specified on the filesystem (not on the classpath), relative to the directory where the OSGi container is started.
keyManagers/keyStore/@password
- The keystore password that unlocks the keystore.
trustManagers/@resource
- The location of the Java keystore file containing one or more trusted certificates (that is, the CA certificates that have been used to sign X.509 certificates from trusted clients). This location is specified on the filesystem (not on the classpath), relative to the directory where the OSGi container is started.Strictly speaking, this property is not needed, if clients do not send certificates to the Jetty service.
trustManagers/@password
- The keystore password that unlocks the
truststore
trust store.
You must also modify the URI at the start of the route (the
uri
attribute of the from
element). Make sure that the scheme of the URI matches the secure Jetty component, jetty
, that you have just created. You must also change the protocol scheme from http
to https
.
Note
Always double-check you have changed the protocol scheme to
https
. This is such a small change, it is easy to forget.
Build the bundle
Use Maven to build the bundle. Open a command prompt, switch the current directory to
ProjectDir/jetty-security
, and enter the following command:
mvn install -Dmaven.test.skip=true
This command builds the bundle and installs it in your local Maven repository.
Install the camel-jetty feature
If you have not already done so, start up the Apache ServiceMix console (and container instance) by entering the following command in a new command prompt:
./fuse
The
camel-jetty
feature, which defines the bundles required for the Camel/Jetty component, is not installed by default. To install the camel-jetty
feature, enter the following console command:
JBossFuse:karaf@root> features:install camel-jetty
Deploy the bundle
To deploy and activate the bundle, enter the following console command:
JBossFuse:karaf@root> osgi:install -s mvn:org.jbossfuse.example/jetty-security
The preceding command loads the bundle from your local Maven repository. You might need to configure the Mvn URL handler with the location of your local Maven repository, if the bundle cannot be found (see section "Mvn URL Handler" in "Deploying into the Container").
Test the bundle
To test the Jetty service, enter the following
curl
command at a comand-line prompt:
curl https://0.0.0.0:8282/services -k
Note
Don't forget to use
https:
instead of http:
in the URL!
The
-k
flag allows curl
to skip the SSL certificate check (that is, checking that the received server certificate is signed by a local CA certificate), so that the server identity is not verified. You should receive the following HTTP response:
<html><body>Hello from Fuse ESB server</body></html>
Uninstall the bundle
To uninstall the broker bundle, you need to know its bundle ID, BundleID, in which case you can uninstall it by entering the following console command:
JBossFuse:karaf@root> osgi:uninstall BundleID