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:generate -DarchetypeGroupId=org.apache.maven.archetypes -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 Apache Karaf".
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>4.11</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
In a convenient location, create the
clientKeystore.jks
key pair and the serviceKeystore.jks
key pair using the Java keytool
utility, as follows:
keytool -genkeypair -keyalg RSA -dname "CN=Client, OU=Engineering, O=Red Hat, ST=Dublin, C=IE" -validity 365 -alias client -keypass KeyPass -keystore clientKeystore.jks -storepass StorePass keytool -genkeypair -keyalg RSA -dname "CN=Service, OU=Engineering, O=Red Hat, ST=Dublin, C=IE" -validity 365 -alias service -keypass KeyPass -keystore serviceKeystore.jks -storepass StorePass
Copy the
clientKeystore.jks
certificate and the serviceKeystore.jks
certificate 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 store 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.jetty9.JettyHttpComponent9"> <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="KeyPass"> <keyStore resource="etc/certs/serviceKeystore.jks" password="StorePass"/> </keyManagers> <trustManagers> <keyStore resource="etc/certs/serviceKeystore.jks" password="StorePass"/> </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 JBoss Fuse console (and container instance) by entering the following command in a new command prompt:
./bin/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/1.0-SNAPSHOT
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 Apache Karaf").
Test the bundle
To test the Jetty service, enter the following
curl
command at a comand-line prompt:
curl https://localhost: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