0

I have a java cucumber test automation framework that I am using for testing apis.

Previously I was using a tool called Karate that has a simple flag ( karate.configure('ssl', { trustAll: true });) that allows you to trust all certificates.

I was hoping there would be a similar flag for use with Apache HTTP Client...but all my googling leads to long and complicated code.

This is the code I have written so far to send the .pfx file to the api

        String keyPassphrase = "";

        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new FileInputStream("src/main/resources/sslCertificates/certificate.pfx"), keyPassphrase.toCharArray());

        SSLContext sslContext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, null)
                .build();


        //This is the httpClient that you will use to send your http request
        CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();

        //Send the request
        CloseableHttpResponse response = httpClient.execute(request);

but it gets rejected before it is sent saying

 "javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"

How can I easily accept all certificates to get around this problem? As stated I am just testing so there is no problem with doing this.

However I do have certificate files in .pfx and .crt formats and a client.key file that could potentially be used - but I don't know how.

Matt
  • 773
  • 2
  • 15
  • 30

2 Answers2

0

I used the solution mentioned in this post:

Getting Java to accept all certs over HTTPS

There, you build a custom TrustManager and HostNameVerifier to accept any certificate and domain:

Custom implementation of HostNameVerifier:

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

public class TrustAllHostNameVerifier implements HostnameVerifier {

    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
}

Https connection creation:

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    HttpsURLConnection.setHostnameVerifier(new TrustAllHostNameVerifier())
} catch (Exception e) {
  :
  :
}

Although you clarified that it's for testing purposes, it's important to remember that this is an extremely insecure solution where you lose all the protection given by the use of SSL.

  • Thanks Ernesto...I created my own KeyManager and then merged that into your code. It is working now! – Matt Mar 04 '22 at 16:16
0

You can do the following if using HttpClient 4.4 or above (the example was taken from the reference below):

TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, 
      NoopHostnameVerifier.INSTANCE);
    
    Registry<ConnectionSocketFactory> socketFactoryRegistry = 
      RegistryBuilder.<ConnectionSocketFactory> create()
      .register("https", sslsf)
      .register("http", new PlainConnectionSocketFactory())
      .build();

    BasicHttpClientConnectionManager connectionManager = 
      new BasicHttpClientConnectionManager(socketFactoryRegistry);
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
      .setConnectionManager(connectionManager).build();

More details here: https://www.baeldung.com/httpclient-ssl

pringi
  • 3,987
  • 5
  • 35
  • 45