This is a technote for myself for the future and perhaps a note that’ll help people searching for this obscure but important and confusing tech roadblock.
I’m working on a web app. It’s hosted at Azure, a platform that grows more and more impressive every day.
As we all know by now, any respectable web app needs a full https trusted connection, which is best for customer privacy, and now appropriately mandated by Google, Facebook and the like.
Now, with plain-vanilla web apps, Azure has a very handy SSL provisioning process which does the grunt-work for you, and gets basic SSL certificates up and running and even custom domain names assigned. I recommend it.
But with my app, I’ve got some specific reasons beyond the scope of this article as to why I needed to provision this certificate manually, which have to do with the fact that it’s an Angular Universal app, running on Node/Express on the back end, with an Azure Application Gateway on the front-end, which doesn’t yet appear to robustly support automatic certificate provisioning.
The point is, to get a fully trusted https (SSL/TLS) connection, you need to install both a main certificate and any intermediate certificates at the server. Or more accurately, you need a single certificate with both the “main” certificate and any “intermediate” certificates.
At this writing, Azure’s Application Gateway service insists that this be a single certificate in PFX format.
Complicating matters further is that vendors like GoDaddy (which is the one I use) issue certificates in .crt and .p7b formats. You don’t get a PFX certificate from GoDaddy. You get a .crt (main) certificate and a .p7b (intermediate) certificate when GoDaddy thinks their work is “done.”
So there you are, needing a .PFX and only having (and having paid hundreds of dollars for) a .crt and a .p7b.
So, off to Google you go. You quickly find that you can convert the .crt to a .pfx, and that does appear to work.
But… and with Certificate Hell, there’s always a gotcha!… if you solely focus on the main certificate that GoDaddy (or others) issue, you’re given the illusion of it working but it really isn’t right, end-to-end.
It will appear to work on, say, Google Chrome, presenting you with the nice shiny lock icon. But then, you head on over to Facebook’s “Linter” (their social media debugger), and it will bark at you that the SSL of your site is invalid. So will more complete tools like SSL Labs Validity Checker.
That’s because it’s missing the Intermediate Certificate. This certificate is essentially telling the Internet that GoDaddy has the rights to issue certificates for domains, and that this “main” certificate has been issued by the real GoDaddy itself.
And with so many steps in this process, the error messages you get don’t always point in the right direction. Because why would you want to do that if your goal is to maximize complexity?
In general, you need a certificate which contains the full “chain” of trust, and in my case, it included both the final certificate as well as GoDaddy’s intermediate certificate. This all needs to be bundled into a single PFX file in the end.
That’s what most Azure services want — a final PFX that includes any intermediate certificates in the chain.
Too Much Confusing Jargon
The maddening bit about all this is that the documentation seems written by people from NASA, and uses overly complex lingo and jargon. Even the many helpful people on StackOverflow and the like make all kinds of assumptions about what you know and what you don’t.
So how do you get it all to work?
I spent much of this weekend trying various approaches. So many dead-ends. Such a pain!
But I finally solved it. Here are the steps.
First, buy an “SSL Certificate” from a vendor, such as GoDaddy. At GoDaddy at least, buying an SSL certificate gives you a “slot” to begin the process. You tell it the domain name you want. Better yet, go with a wildcard domain; you should always think about buying a wildcard like *.domainname.com, because in many cases, you’ll very likely want to secure subdomains.
This gives you a spare “SSL Certificate” process to initiate in the “My Products” area. Click on that to get started.
Go to a Windows machine and open up a terminal. Make sure you have openssl downloaded and installed somewhere on your system PATH.
Note to self: DO NOT try this process using the IIS initiation process, documented in a lot of places on the Web. That for me was one of many dead-ends and confusing aspects to the whole thing. You can complete the entire process with openssl at a terminal, and uploading to GoDaddy, downloading the certificates, and some conversion. Doing so, you will not need any of the “Add/Remote Snap In” MMC gobbledygook.
You do not need to touch the remote server until you have the final .PFX file. It is perfectly OK to initiate an SSL certificate signing request on a development machine and uploading it to the final (say, Azure-hosted) server later. A certificate, once issued, can be uploaded to different machines.
Note also that I only had luck on Windows after trying both OSX and Windows, but I do know from elsewhere on Stack Overflow that it works on OSX too. OSX should work fine, but in a couple of attempts I had difficulties — very likely user error.
First, generate yourself a private key:
openssl genrsa -out myserver.key 2048
That’ll create a file called “myserver.key” in your current directory. This is your private key, hashed to your machine that you generated it from, known only to you. It says “I am the one creating this request.”
Use openssl to generate a certificate signing request:
openssl req -new -key myserver.key -out myserver.csr
Clarifying the Prompts at CSR Time
The prompts during the Certificate Signing Request generation aren’t clear at all. But it’s VERY important what you enter when generating the Certificate Signing Request.
The most important thing is what you enter in the “Common Name” field. This should be your domain name (e.g., domainname.com) or your wildcard (*.domainname.com).
For good measure, I put it as Organization Name as well.
Once it saves a .csr (certificate signing request) file, upload that CSR, including the —- BEGIN CERTIFICATE REQUEST —– and —– END CERTIFICATE REQUEST —— markers to initiate the request.
After five-ten minutes of verification, you’ll be issued a download payload. Grab it in IIS format.
Included in that file will be a main certificate (marked .crt) and an Intermediate certificate (maddeningly in a different format, .p7b.)
Ignore that intermediate certificate issued in the download and INSTEAD (if you’re using GoDaddy) visit GoDaddy’s repository of primary and intermediate certificates to grab their Intermediate Certificate gdig2.crt.pem:
Don’t be scared of .pem and .crt files — they’re just text files. You’re going to open your main .crt file in Notepad++ and APPEND the intermediate certificate from GoDaddy from their repository, saving them both as a file called, say, both.crt.
The Crucial Step: Use Notepad++ to Combine the Certificate Files — Your Main One FOLLOWED by the Intermediate One
You are literally pasting a text file of the two certificates, including the begin/end markers, one after the other. Save that file as something like “both.crt” (meaning, both your main certificate and your intermediate certificate.)
Note that you need this file in pure UTF-8 format. Windows gives you files downloaded in UTF-8-BOM format which is NOT recognized by the openssl tool and you will get an error if you try to use it. In my experience, this can also hork your requested files, so double-check your work before you continue. You should have a file called “both.crt” which includes the full contents of your issued main “.crt” file, followed by the godaddy intermediate certificate above. (Again, that’s only if your SSL cert is issued by GoDaddy and only if it relies upon an intermediate certificate.)
Be sure to use Notepad++ to check the encoding of the text file, and if necessary, switch the encoding type to just UTF-8. It matters. openssl is very finicky, and hates input files in other formats, and your process may fail, requiring you to start all over again.
Once you have everything in a single place, you can get the needed PFX file with this command:
openssl pkcs12 -export -in both.crt -inkey my.key -out www-example-com.pfx
Finally, you should have a completed .pfx file, which includes not just the final certificate but the full chain of authority. (Facebook and Firefox both require full chains of authority, so if you only include the final certificate, it may work on some browsers but others will find it “untrustworthy”.)
This final .PFX file can then be uploaded to Azure. And voila! Use the Facebook Linter and force a refresh of the page and it’ll be happy again.
How was your weekend? 🙂
Useful articles in this journey:
and this one in particular:
- Wild, Wild Georgia - November 6, 2020
- Are We Overstating COVID Positives? - October 1, 2020
- Seattle Plows Ahead with 50% Cut To Police Department. Where are the Metrics Which Define Success? - July 11, 2020