SSL cert import at client end

From a Java client, I am invoking a proxy API and its "One way TLS" communication.

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

After importing the pub cert into "\jre\lib\security\cacerts", able to hit the proxy from local java client.

Is there anyway to hit the proxy from local client without importing public cert at client end??

Note: Server cert on Apigee is issued by a trusted third party and the root cert is there in "cacerts" by default from JDK.

Tried below steps:

1) Created a keystore with private key at Apigee end with the entire chain in a single PEM file. (server_cert --> intermediate --> root)

2) Restarted the routers.

3) Getting the same "PKIX path building failed" error from java client.

Any thoughts??

Solved Solved
0 2 796
1 ACCEPTED SOLUTION

The first thing to check is the certificate signing chain. I'm not clear on which certs are present where. Can you be more specific and explicit in your description?

You said "server cert on Apigee is issued by a trusted third party". . . But specifically which third party? Can you describe your understanding of the chain of CAs for me, explicitly? Give me something like this:

cert1 - attached to vhost

cert1 is signed by CA1 (non-root). What is the name of this CA?

cert for CA1 is signed by ...whom? (root) . What is the name of this CA?

Then, verify that the server (your Apigee-hosted API endpoint) is serving the chain as you expect, using openssl. A good description for how to do this is available here. Basically you will do something like this:

openssl s_client -connect dnsname:443  -showcerts

The dnsname should be whatever you have specified as the Vhost alias. If you are using SNI, you need to modify that command to explicitly specify the particular hostname. Something like this:

openssl s_client -connect dnsname:443 -servername vhostalias  -showcerts

----

Also, what version of Java are you using on the client? Older versions of Java do not support SNI correctly.

For Java7, Oracle introduced SNI support in the Java client libraries, but there were various bugs.

These problems persisted in Java 8, through Update 141.

Java 9 seems to have a correct client-side implementation of SNI. Your safest approach is to use Java9.

You may ask, what is SNI, exactly? Here's a quick article that discusses it.

---

You may also want to check the connection with curl. The current curl implements SNI correctly on the client side. If you can verify that curl trusts the API endpoint, then that will show you that the cert is correct and trusted according to Curl's certificate store. In that case, you would know that the problem you are seeing is strictly an issue related to your Java client - either your version of Java, the contents of the cacerts file (which may be different from the contents of the list of certs trusted by curl!), or the code you're using in the Java client.

View solution in original post

2 REPLIES 2

The first thing to check is the certificate signing chain. I'm not clear on which certs are present where. Can you be more specific and explicit in your description?

You said "server cert on Apigee is issued by a trusted third party". . . But specifically which third party? Can you describe your understanding of the chain of CAs for me, explicitly? Give me something like this:

cert1 - attached to vhost

cert1 is signed by CA1 (non-root). What is the name of this CA?

cert for CA1 is signed by ...whom? (root) . What is the name of this CA?

Then, verify that the server (your Apigee-hosted API endpoint) is serving the chain as you expect, using openssl. A good description for how to do this is available here. Basically you will do something like this:

openssl s_client -connect dnsname:443  -showcerts

The dnsname should be whatever you have specified as the Vhost alias. If you are using SNI, you need to modify that command to explicitly specify the particular hostname. Something like this:

openssl s_client -connect dnsname:443 -servername vhostalias  -showcerts

----

Also, what version of Java are you using on the client? Older versions of Java do not support SNI correctly.

For Java7, Oracle introduced SNI support in the Java client libraries, but there were various bugs.

These problems persisted in Java 8, through Update 141.

Java 9 seems to have a correct client-side implementation of SNI. Your safest approach is to use Java9.

You may ask, what is SNI, exactly? Here's a quick article that discusses it.

---

You may also want to check the connection with curl. The current curl implements SNI correctly on the client side. If you can verify that curl trusts the API endpoint, then that will show you that the cert is correct and trusted according to Curl's certificate store. In that case, you would know that the problem you are seeing is strictly an issue related to your Java client - either your version of Java, the contents of the cacerts file (which may be different from the contents of the list of certs trusted by curl!), or the code you're using in the Java client.

Hi Dino,

Thanks for your response.

The command you provided has actually helped me to know that the cert chain added to Apigee keystore is not getting reflected.

<Code>openssl s_client -connect dnsname:443 -showcerts</Code>

The reason for this is that at client's environment, the SSL handshake is happening before reaching Apigee Router, at load balancer.

Once the cert chain was added at load balancer, able to hit the API from java client without importing the cert. JDK version: jdk1.8.0_171

Thank you