Sunday, September 14, 2014

CA-signed SSL Certificates with Node

Summary

I just recently went through the exercise of bringing up a Node HTTPS server with 'real' SSL credentials (meaning, not a self-signed certificate).  Although there's a lot of bits and pieces of info out there on the Interweb on how to obtain a CA-signed certificate, configure Node HTTPS, etc - I couldn't find a concise guide in any one place on how to do a real-world SSL implementation with Node.  Below is an attempt to provide clear guidance and hopefully save you some time if you ever have to configure this.

Step 1:  Generate a CSR
Below is the openSSL command to create a 2048-bit private key and certificate signing request (CSR - that will contain the corresponding public key).  That command will generate a series of questions for info required in a CSR. At a minimum, you'll need to provide a legitimate Common Name (a domain name you control) and email address.
openssl req -nodes -newkey rsa:2048 -keyout yourPrivate.key -out yourServer.csr


Step 2:  Submit the CSR to CA
I went with Comodo as my CA for this exercise.  They currently provide a 90-day free SSL certificate.  Additionally, I thought their cert request process was well-documented and easy to use. That request process amounted to a copy/paste of the text of the CSR to their web form and then proof that I actually controlled the domain in question.  That can be accomplished in multiple ways (email to the domain, CNAME mods, etc).  After Comodo has that proof, they'll send an email to you with a zip archive containing the following files:

  1. Certificate file.  Example:  yourDomain_com.crt
  2. Certificate chain file.  Example:  yourDomain_com.ca-bundle
Step 3:  Combine SSL Credentials into a PKCS #12 file
This is the part that took some time and digging to figure out.  Simply putting the credentials you've created/received into the HTTPS options on the createServer call doesn't cut it.  The problem is with that chain file.  It needs to be passed as an array for the 'ca' option.  That doesn't happen with just a fs.read.  You wind up with SSL errors when a client attempts to connect to a server with this config.


//WILL NOT WORK
var privateKey = fs.readFileSync('/path/to/yourPrivate.key');
var certificate = fs.readFileSync('/path/to/yourDomain_com.crt');
var certAuth = fs.readFileSync('/path/to/yourDomain_com.ca-bundle');
var credentials = {key: privateKey, cert: certificate, ca: certAuth};

var appHttps = express();
var httpsServer = https.createServer(credentials, appHttps).listen(yourHttpsPort);



Folks have written some examples on how to parse out that chain file into an array that Node can digest, but I ran across a post with a the better idea of just combining all three files into one PKCS file with the openSSL command below:

openssl pkcs12 -export -out yourDomain.com.pfx -inkey yourPrivate.key -in yourDomain_com.crt -certfile yourDomain_com.ca-bundle



Now, you can do the following:


//THIS WORKS
var pfxFile = fsys.readFileSync('/path/to/yourDomain.com.pfx');
var credentials = {pfx: pfxFile};
var appHttps = express();
var httpsServer = https.createServer(credentials, appHttps).listen(yourHttpsPort);
Copyright ©1993-2024 Joey E Whelan, All rights reserved.