Using ssl certificate with feign

Viewed 9503

I'm trying to acess a apllication secured by https, i have a p12 certificate (already imported as .cer into cacerts folder of my jdk).

I already tried this tutorial to no success: https://dzone.com/articles/ssl-based-feignclient-example-in-java-microcervice

And also i'm using part of this solution: How to use p12 client certificate with spring feign client

Debuging the ssl connection i get the following error: javax.net.ssl|ERROR|25|http-nio-auto-1-exec-1|2021-01-26 16:56:34.789 BRT|TransportContext.java:317|Fatal (HANDSHAKE_FAILURE): Received fatal alert: handshake_failure

My current feign config class

    @Bean
    @ConditionalOnMissingBean
    public Feign.Builder feignBuilder(Retryer retryer) {
        return Feign.builder().retryer(retryer);
    }
    
    @Bean
    public Feign.Builder feignBuilder() {
        return Feign.builder()
            .retryer(Retryer.NEVER_RETRY)
            .client(new Client.Default(getSSLSocketFactory(), null));
    }
    
    private SSLSocketFactory getSSLSocketFactory() {
        String keyStorePassword = "myPassword";
        char[] allPassword = keyStorePassword.toCharArray();
        SSLContext sslContext = null;
        try {
            sslContext = SSLContextBuilder
                .create()
                .setKeyStoreType("PKCS12")
                .loadKeyMaterial(ResourceUtils.getFile("keypath"), allPassword, allPassword)
                .build();
        } catch (Exception e) {  }
        return sslContext.getSocketFactory();
    }

In the debbuging section of the code i can see my certificate is there, but still my java is getting the handshake error. I'm new to ssl concept and possible did some config wrong.

One last note, when in the feign config class and set the trust store and password by System

         System.setProperty("javax.net.ssl.trustStorePassword", "pass");
        System.setProperty("javax.net.ssl.trustStore", "pathtocerth.p12");

The error change to this:

javax.net.ssl|ERROR|25|http-nio-auto-1-exec-1|2021-01-26 16:48:58.551 BRT|TransportContext.java:317|Fatal (CERTIFICATE_UNKNOWN): PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

2 Answers

I'm answering myself since i found out the problem. Case someone face the same issue the solution is quite simple.

Inside application properties you need to add these properties:

feign.httpclient.disableSslValidation=true
feign.httpclient.enabled=false
feign.okhttp.enabled=true

From

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>9.4.0</version>
</dependency>

Set the feign configuration class

@Configuration
public class CustomFeignConfiguration {

    @Bean
    public void Config() {  
        System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");    
        System.setProperty("javax.net.ssl.keyStore", "path to p12");  
        System.setProperty("javax.net.ssl.keyStorePassword", "key password"); 
    }

And use the feign config in the feign request

@FeignClient(name = "foo", url = "https://foo/foo",
configuration = CustomFeignConfiguration.class)
public interface IFeingRequest {

request here

}

With this solution I did NOT need to convert the certificate and store it into java trust store.

You can add the key (and additional trust store optionally) directly via application properties in Spring.

server:
  ssl:
    #trust-store: path_to_your_truststore
    #trust-store-password: changeit
    #trust-store-type: JKS
    #trust-store-provider: SUN
    key-store: path_to_your_keystore
    key-store-password: changeit
    key-alias: 1
    key-store-type: PKCS12
    key-store-provider: SUN
    key-password: changeit
    protocol: TLS

To identify the key-alias, key-store-type and key-store-provider, you can use the following command:

keytool -list -keystore  path_to_keystore

But if you just want to turn off hostname verification, then you don't need above. You can configure it for feign httpclient by adding these properties:

feign.httpclient.disableSslValidation=true

and this maven dependency:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

No need for okhttp.

Related