If you’re getting errors in calling out to https urls from CF, you may not need to “import new certificates”. You may merely need to update the JVM that CF uses.
Sometimes the solution to a problem is not what many may suggest it is. Over the years I have had clients present to me (or have seen people write on the web ) that they were getting errors when trying to do a cfhttp call to an https URL:
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
I/O Exception: peer not authenticated
You might see the same in the saved output of a CF scheduled task.
And such folks have found various blog posts (perhaps from years gone by) suggesting that the “solution” was a need to import a new SSL certificates into CF using the Java keytool command, or to add args like -Dhttps.protocols=TLSv1.1,TLSv1.2. That may NOT be the needed (or even best) solution. See below for more.
TLDR: I have found that in most cases the solution for such failing ssl/tls calls out of cf is much simpler, and it could benefit many readers to hear this: they probably just needed to update their JVM (that CF was using). Importing certs may well have been needed for some problems in the past (and may be needed still in some unique cases), but in many cases, it’s NOT needed to solve the above.
Let me explain.
What might be the real cause of the problem?
Those two problems above are indeed different, and have different causes, but again they both may be solved by just updating the CF JVM.
First, a very common reason for this sort of problem is simply that the destination server being called (such as in a CF scheduled task, cfhttp, cfmail, cfftp, etc.) has changed what SSL or TLS versions or protocols it supports. And it may now be using a version of those which the JVM that CF is relying on DOES NOT YET SUPPORT. And that JVM CF is relying on may not have been updated in years, as I will explain below.
Second, the destination server may well have changed something about its server certificates, such that the client certs (or root certs) stored within the CF JVM can no longer work with those newer certs. These may be certificates that you did install in the past, or they merely be the ones built into the java certificate store (cacerts, in the lib/security folder of the JVM that CF is using), but now they “don’t work”, again because the server you’re calling has changed, and the JVM (and perhaps default certs) that it uses no longer work.
These are how the errors above you experience can appear “suddenly”, when you “haven’t changed anything”. The change was made in the server or service you are calling, like a payment gateway, or a web service, or some API server, etc. (And worse, it may be that the URL you’re calling is served by a load balancer, and perhaps one of the servers in that cluster was NOT updated, so the problem you see may “come and go”!)
Why updating the JVM that CF uses may help
Anyway, often the problem is simply that the JVM which underlies CF is just old (perhaps very old). Over the years, the JVM has been updated to support more and more recent protocols (and indeed to drop support for older ones), and to have more and more updated certs by default. In the case of the client which prompted me to go ahead and write this, they were running on ColdFusion 11 as I said, but this could happen with other CF versions–even the latest CF version, if the JVM it’s using has itself not been updated in months or years, which can easily happen.
In the case of this one client of mine, they had left CF running the original JVM that came out with CF 11, which was Java 1.8.0_25. To put things in perspective, as of this writing (2019), that JVM update 25 was 5 years old!, being from 2014, the time when CF11 also came out! FWIW, the latest Java 8 version at this writing is 1.8.0_212 (and Oracle is still updating Java 8 and 11, as “long term support” releases of Java.)
So all we did was to simply install Java 8 update 212 (from Apr 2019) and tell CF to use that, and restarted CF, and now his https calls via cfhttp and scheduled tasks were working!
How to go about updating the JVM CF uses: questions you may have
When I say “all we did was to simply update” the Java that underlies CF, you may have lots of questions about that. 🙂 Here’s good news, when the most recent Java updates (212 for Java 8, and 4 for Java 11 at the time of this writing) came out in April, I did a blog post where I addressed typical questions you may have about updating the JVM, including:
- where to download the latest Java updates, from Adobe (and why)
- where to find more about HOW TO update the JVM CF that uses
- what versions of CF support what versions of Java, including Java 11
- why you should NOT use Java 12, even though it’s “more recent” than Java 11
- how to recover if you make a mistake trying to update the JVM CF that uses
(I should add that even updating to even slightly older Java update than the very latest one possible could solve this problem as well, for those who “don’t want to be on the bleeding edge” of latest Java updates. But it’s generally best to be on the latest available update of the Java version supported by your version of CF, and Adobe does recommend that.)
Whether you’ll be updating to that specific Java update or not, check do out that other post for answers to those and some other common questions about updating the JVM that CF users.
What you may not need to bother with
So really, that was it: update the JVM. They really did not need to do any other jvm tweaks.
First, they did not need to import certificates after all. You may see resources on the web proposing that. Indeed, one of the resources my client had found (which led them to ask if they needed to go about importing a new cert) was this blog post of years ago from the venerable hass.de site.
He was explaining why importing certs may be needed to solve some SSL problems. And sometimes it may be. Again, for example, my client prompting this post was using CF11 and the original Java 1.8.0_25 which came out 5 years ago. It may well be that such an old JVM had expired certificates and root certs, leading to a need for some (at some time in the past) to do such cert imports, before a newer jvm included the better certs. (Indeed, sometimes people have been importing certs by rote for years thinking they needed them, when instead all they needed was to update the JVM to get the better certs and root certs it would have by default.)
But again just updating Java worked for my client and I hope it may for some of my readers.
And that hass.de blog did indeed mention in passing that “an update to latest Java sometimes also help, too.” That would be easy to miss amid all else in the post. One reason I point this out here is that sadly that hass.de site no longer allows comments, so I couldn’t add this clarification there. (I get it that more and more sites are not permitting comments. I see the pros AND cons.)
Second, as for why adding the Dhttps.protocols arg may not help or be needed: again you may see resources on the web proposing adding those as a solution for some cf ssl issues. But it is not the right solution for this more common problem (of the destination server changing what it supports, and that being something that the JVM CF is running on does NOT support).
This Dhttps.protocols arg would be for limiting what protocols CF/the JVM should use. But the SSL negotiation between CF and the destination server (such as in a CFHTTP call or scheduled task URL) should cause CF to use whatever the best protocol the destination DOES support. But again, if the ones that the destination DOES support are not ones that the JVM underlying CF supports, you will get the error. As such, the args won’t help, and really it’s rare that you need this arg anyway to “limit” what protocols CF would try to use.
Bottom line: Try updating the Java that CF uses
My goal here was just to get the word out that for THAT error above (and perhaps other failures to call out of CF to https pages), you may not need to bother importing certs. You may just need to update the JVM. It’s worth a shot. And you can easily revert back to the previous JVM version, if you follow best practices in updating the JVM that CF users, as discussed in resources I point out in that other post.
Hope all this may help some readers.