0

I am trying to create a org.apache.http.impl.client.CloseableHttpClient that trusts self signed certificates.

Here is the code I have tried:

private void makeCall() {
    CloseableHttpClient httpClient = HttpClientBuilder.create()
                    .setSSLContext(
                            new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()
                    )
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .build();
    HttpGet httpget = new HttpGet("https://selfSignedCertSite.somedomain.com/");
    try {
        try (CloseableHttpResponse response = httpClient.execute(httpget)) {
            System.out.println(response.toString());
        }
    }catch(Exception e){
        //PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        System.out.println(e.getMessage());
    }
}

I still get an exception with the following message:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I do not want to change JKS files as my app is using all default ones and I want to configure it using code only.

How do I do it?

Jerald Baker
  • 1,121
  • 1
  • 12
  • 48
  • You need to create your own `KeyStore` (with the self-signed cert) and `SSLContext`. Then init the `SSLContext` with `SSLContext::init`. – zhh Feb 14 '22 at 09:48
  • Check if this helps: https://stackoverflow.com/questions/39922714/ignore-self-signed-certificates-in-apache-httpclient-4-5 – pringi Feb 14 '22 at 09:49

1 Answers1

0

I figured it out. The problem is, I was using TrustSelfSignedStrategy(). This works only if the cert chain has a length of 1 according to the implementation of isTrusted(..) method in TrustSelfSignedStrategy()

However, the site I was trying to access presents a self signed cert with chain length as 2. (k8s k8s, which uses self signed intermediate ca + leaf)

So the solution is to use a custom TrustStrategy that trusts certs even if length = 2 or more generally, just return true for all as below :-

private void makeCall() {
    CloseableHttpClient httpClient = HttpClientBuilder.create()
                    .setSSLContext(
                            new SSLContextBuilder().loadTrustMaterial(null, (TrustStrategy) (x509Certificates, s) -> true).build()
                    )
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .build();
    HttpGet httpget = new HttpGet("https://selfSignedCertSite.somedomain.com/");
    try {
        try (CloseableHttpResponse response = httpClient.execute(httpget)) {
            System.out.println(response.toString());
        }
    }catch(Exception e){
        //PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        System.out.println(e.getMessage());
    }
}
Jerald Baker
  • 1,121
  • 1
  • 12
  • 48
  • 2
    A cert with a trust chain of 2 is no longer self-signed. It is a cert with a custom CA. Instead of trusting all certs indiscriminately you should trust to that custom CA in addition to standards CAs recognized by the JRE. – ok2c Feb 14 '22 at 16:12