Murphy85
Murphy85

Reputation: 643

Apache camel http4 with self signed SSL certificate

I'm really stuck configuring Apache camel https4 for self signed server certificates that does not match the hostname.

[Do. 2020 16 Juli 13:13:19] [DEBUG] org.apache.camel.processor.Pipeline () - Message exchange has failed: so breaking out of pipeline for exchange: Exchange[ID-lvm-cdbservice-01ct-1594888044674-0-15551] Exception: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

That's why I created a custom HttpClientConfigurer as stated in the apache camel http configuration. But this configurer does not seem to be used for my route?! Does anybody know why?

The configureHttpClient method is used at some point

[Do. 2020 16 Juli 10:27:25] [INFO ] com.test.SelfSignedHttpClientConfigurer () - Using SelfSignedHttpClientConfigurer...
[Do. 2020 16 Juli 10:27:25] [INFO ] com.test.SelfSignedHttpClientConfigurer () - ... HttpClient configured!

But the protocols didn't change. That's why I guess it is not used for my route.

available protocols [[TLSv1.3, TLSv1.2, TLSv1.1, TLSv1]],
currently enabled protocols [[TLSv1.3, TLSv1.2, TLSv1.1, TLSv1]],
and default protocol patterns [Patterns [includes=[.*], excludes=[SSL.*]]].
Resulting enabled protocols are [[TLSv1.3, TLSv1.2, TLSv1.1, TLSv1]].

pom.xml

<properties>
    <camel.version>2.24.3</camel.version>
</properties>

<dependencies>
    <!-- camel -->
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-core</artifactId>
        <version>${camel.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-spring</artifactId>
        <version>${camel.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-http4</artifactId>
        <version>${camel.version}</version>
    </dependency>
</dependencies>

applicationContext.xml

<!-- Apache Camel -->
<camelContext
    xmlns="http://camel.apache.org/schema/spring">
    <!-- HTTP myTime -->
    <route id="myTimeRoute">
        <from uri="file:///tmp/test?consumer.delay=10000" />
        <setHeader headerName="CamelHttpMethod">
            <constant>POST</constant>
        </setHeader>
        <setHeader headerName="Content-Type">
            <constant>application/json</constant>
        </setHeader>
        <to uri="https4://test.de/test?delay=60000&connectTimeout=20000&httpClientConfigurer=#selfSignedHttpClientConfigurer&sslContextParameters=#mySSLContextParameters&throwExceptionOnFailure=false" />
    </route>
</camelContext>

<bean id="selfSignedHttpClientConfigurer"
    class="com.test.SelfSignedHttpClientConfigurer" />

I tried it with and without # (httpClientConfigurer=#selfSignedHttpClientConfigurer and httpClientConfigurer=selfSignedHttpClientConfigurer)

SelfSignedHttpClientConfigurer.class

package com.test;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;

import org.apache.camel.component.http4.HttpClientConfigurer;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SelfSignedHttpClientConfigurer implements HttpClientConfigurer {

    /** the logger. */
    private static final Logger LOG = LoggerFactory.getLogger(SelfSignedHttpClientConfigurer.class);

    @Override
    public void configureHttpClient(HttpClientBuilder clientBuilder) {

        try {
            LOG.info("Using SelfSignedHttpClientConfigurer...");

            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();

            // Allow TLSv1.2 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1.2" },
                null, NoopHostnameVerifier.INSTANCE);

            clientBuilder.setSSLSocketFactory(sslsf);

            LOG.info("... HttpClient configured!");

        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        }
    }
}

I tried with .build() and without.

Upvotes: 5

Views: 5802

Answers (1)

Murphy85
Murphy85

Reputation: 643

I finally found a solution. All the tutorials and documentations are "deprecated", because the Apache HTTP API has changed with version 4.5. You will not get any errors in your code, but it is simply not working.

This post really helped me: https://stackoverflow.com/a/38509015

SelfSignedHttpClientConfigurer.class

package com.test;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;

import org.apache.camel.component.http4.HttpClientConfigurer;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SelfSignedHttpClientConfigurer implements HttpClientConfigurer {

/** the logger. */
private static final Logger LOG = LoggerFactory.getLogger(SelfSignedHttpClientConfigurer.class);

    @Override
    public void configureHttpClient(HttpClientBuilder clientBuilder) {

        try {
            LOG.info("Using SelfSignedHttpClientConfigurer...");

            final SSLContext sslContext = new SSLContextBuilder()
                .loadTrustMaterial(null, (x509CertChain, authType) -> true).build();

            clientBuilder.setSSLContext(sslContext)
                .setConnectionManager(new PoolingHttpClientConnectionManager(RegistryBuilder
                        .<ConnectionSocketFactory> create().register("http", PlainConnectionSocketFactory.INSTANCE)
                        .register("https",
                                new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE))
                        .build()));

            LOG.info("... HttpClient configured!");

        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        }

    }

}

applicationContext.xml

<!-- Apache Camel -->
<camelContext
    xmlns="http://camel.apache.org/schema/spring">
    <!-- HTTP myTime -->
    <route id="myTimeRoute">
        <from uri="file:///tmp/test?consumer.delay=10000" />
        <setHeader headerName="CamelHttpMethod">
            <constant>POST</constant>
        </setHeader>
        <setHeader headerName="Content-Type">
            <constant>application/json</constant>
        </setHeader>
        <to uri="https4://test.de/test?httpClientConfigurer=#selfSignedHttpClientConfigurer" />
    </route>
</camelContext>

<bean id="selfSignedHttpClientConfigurer"
    class="com.test.SelfSignedHttpClientConfigurer" />

Upvotes: 7

Related Questions