Search code examples
sslhttpsapache-cameljettyapache-servicemix

Using different SSL certificate per Camel+Jetty route


I have a series of webservices exposed using the Camel Jetty component running in ServiceMix (Fuse). Something like:

<route>
      <from uri="jetty:http://0.0.0.0:25100/service1"/>
      ...
</route>    
<route>
      <from uri="jetty:http://0.0.0.0:25100/service2"/>
      ...
</route>

I want to be able to change them to use https/ssl but I need to be able to use a different key/cert for each route. I've looked at the Jetty Component documentation and it does a decent job of describing how to configure the Jetty Component globally to use SSL but there doesn't seem to be a way to specify different certificates for different routes? From Jetty Component Documentation:

<bean id="jetty" class="org.apache.camel.component.jetty.JettyHttpComponent">
    <property name="sslSocketConnectorProperties">
        <properties>
            <property name="password"value="..."/>
            <property name="keyPassword"value="..."/>
            <property name="keystore"value="..."/>
            <property name="needClientAuth"value="..."/>
            <property name="truststore"value="..."/>
        </properties>
    </property>
</bean>

Is it possible to use different certificates per route?


Solution

  • On any HTTPS server, the certificate is a property that can only be configured for the entire host name.

    HTTPS is HTTP over TLS, that is the SSL/TLS connection is established first, before any HTTP traffic is sent (therefore before any URL path is sent):

    The agent acting as the HTTP client should also act as the TLS client. It should initiate a connection to the server on the appropriate port and then send the TLS ClientHello to begin the TLS handshake. When the TLS handshake has finished. The client may then initiate the first HTTP request. All HTTP data MUST be sent as TLS "application data".

    By the time it could make a decision depending on the path, the certificate has already been sent and the SSL/TLS handshake is over.

    One way that could allow this would be to use distinct host names.

    You could do this by configuring different host names and IP addresses on your server to use a different aliases from your keystore, or use a different port.

    In principle, you could also do this with distinct host names on the same IP address/port using Server Name Indication (SNI); unfortunately, even Java 7 doesn't support it on the server side (only on the client side). A typical workaround for this is to use a single certificate that is valid for multiple hosts, using multiple Subject Alternative Name entries.