Manually Add a New Trusted Certificate to Commandbox's JVM Keystore

I ran into an issue this week where Experian (the credit report provider) updated an SSL certificate in their UAT environment and it caused all cfhttp requests to throw an exception error:

I/O Exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

image

I have experienced this type of issue before with a vanilla ColdFusion install, but never with a Commandbox instance. Here’s how I fixed the issue:

  1. I downloaded the root certificate in Chrome by navigating to the page and clicking on the “lock” icon in the address bar:
    image

  2. Click on “Connection is Secure” and then “Certificate is Valid”
    image

  3. Click on the Certification Path in the Certificate window that pops up and select the appropriate Certification Authority in the path. Click on “View Certificate”:
    image

  4. Click on “Details” and then “Copy to File…” to save the certificate to your hard drive.
    image

  5. Using the Certificate Export Wizard, export the certificate as DER encoded binary (.CER). For this example, I saved it to my downloads folder. "C:\Users\DaveL\Downloads\stg1-ss6-experian-com.cer

  6. Now navigate to the folder on your computer where you saved the file and change the extension from *.cer to *.crt.

  7. Next, figure out where your Commandbox JVM is installed. Within Commandbox type:
    repl 'createObject( "java", "java.lang.System" ).getProperty( "java.home" )' Take note of the folder location. In my case, it was “C:\Program Files\commandbox\jre”.

  8. Now it’s time to add the key to the keystone. Navigate to the “bin” directory inside the JVM directory. In my case, it was “C:\Program Files\commandbox\jre\bin”. Type in the following command:
    keytool -trustcacerts -keystore "[Your JVM Path]\lib\security\cacerts" -storepass changeit -importcert -alias [CertAlias] -file "[Absolute path to your .crt. file]"
    Replace the brackets above with the appropriate paths for your system and .crt file. You should also give the new cert an alias. In my case it looked like this:
    keytool -trustcacerts -keystore "C:\Program Files\commandbox\jre\lib\security\cacerts" -storepass changeit -importcert -alias experian -file "C:\Users\DaveL\Downloads\stg1-ss6-experian-com.crt"

If you’ve changed your keystore password, then you can also change that to whatever value you changed it to.

Once complete, restart your CF server via server restart and you should be ready to rock!

Hopefully, this helps anyone that runs into this issue.

2 Likes

This is a nice guide, however it makes a few assumptions that may not be true for everyone. Firstly, CommandBox doesn’t really have a keystore of its own, but Java installations have one as well as every Lucee server. If you’re making an HTTP connection from the actual CLI like using the REPL or executing a Task Runner or custom command, then you’d need to modify Lucee’s key store that is powering the CLI (found inside the CommandBox home).

It’s also worth noting that adding certs to the keystore isn’t something you should really ever be doing. The “correct” path is to contact the site and ask them why their certs are valid. The error message you received indicated that the root certificate authority or an intermediate cert wasn’t trusted. Simply updating your JRE may have fixed it if yous was simply out of date. In your case, stg1-ss6.experian.com is using a cert that was just issued last month, but is trusted by an intermediate CA which is from 2014, but for some reason was not in my local cacerts file. I’m curious what’s going on there…

Now your specific use case was for a server and it depends on whether you’re using Adobe CF or Lucee. Adobe doesn’t have its own key stores and will use whatever keystore the JVM that started it is using. Lucee servers however have their own keystore which overrides that of the JVM (found in lucee-server\context\security\cacerts). Adding an SSL cert to a Lucee is about 100 times easier. You can do it manually via the Lucee admin or simply run the

sslCertificateInstall( 'host.com' )

from inside your CFML application, restart and you’re golden.

Now in regards to finding what JRE is powering an Adobe ColdFusion server, it’s not necessarily the same one that is powering your CLI (the same is true of any Lucee Server).

This same info can also be found by just running the info command and looking at the Java Path line. But again, that can be misleading. Unless otherwise specified, CommandBox will use the JRE that is powering its CLI to start servers, but CommandBox also has the ability to override the path to your JRE per-server as well as an entire integration with the Adoptium API which can be used to download entire JREs and JDKs on the fly and use them for your servers as you wish. https://commandbox.ortusbooks.com/embedded-server/configuring-your-server/custom-java-version

server start javaVersion=openjdk11

So if you want to see what java installation a given server is using in CommandBox, the proper method would be to run this command:

server info property=javaHome

The keytool bits are pretty standard, but if anyone is looking for a for friendly GUI to do the same work, I like Portecle.

1 Like

Thanks Brad for the additional clarification.

My example was from the perspective of someone using Adobe ColdFusion (ACF) 2018, and not Lucee in this instance. It’s nice to know that the process is much easier in Lucee.

I also found it strange that this particular intermediate CA wasn’t present in the cacerts file. I encountered the same issue with a vanilla ACF 2018 install using jdk-11.0.15.1. You would think an old CA like that would be present in there.

1 Like

I am running into this error. I have been trying all day to get it to work locally. Everything is updated. Using java 11.0.18. Trying to run it with ACF 2021. No matter what I do, I keep getting that original error of

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

I do restart the server. Maybe I am looking at the wrong keystore, if anyone has any more tips to make sure I am pointing to the right place, I would appreciate any help.

@visciousbrick,
Did you try running the info command in Commandbox to see which Java installation you are using?
server info property=javaHome

Did you try Brad’s method of using Portecle?

Maybe you are, but unless you tell us what keystore you imported the cert into, we can’t answer that for you. Also, a common mistake is not to import the entire cert chain.