Working with SSL as Env variables in Node js (Bonus: Connecting Mysql with SSL)
To support one of the most secure connections to application instances like databases, you need to connect via SSL and that usually involves having to download the cert files and making the cert files available in your application before your application can place a successful connection. But how do we make this dynamic? We all know that env variables have come to make it easier to configure your application for different environments and dependencies so why not make it such that our SSL files come in as env variables. Genius!!
TLDR: The Secret is BASE64
If you’re here you’re probably wondering how to go by it and I'm going to show you. As an example, we are going to connect to a MySQL database via SSL. Before you proceed there are certain things you should be familiar with:
- You should be knowledgeable about building apps using Node js.
- The article assumes you have connected via SSL with applications.
- This article assumes you know how to work with env variables.
Just in case you haven’t figured this out already this article is trying to solve the problem where your SSL cert files have to physically exist in your server before you can make a successful SSL connection. This article tries to fix this problem by making the SSL files come in as env variables.
Okay before we begin let us examine the structure of a basic .pem file (which is the format of cert files) to understand our limitations
From the picture above you can see that the cert file has a strict format and copying the text contents as is would compromise the whole file. So our solution must keep the integrity of the file and as such change the file to a clean string format that we then reconvert back to its original format. We can achieve this by using base64 encode and decode. Base64 is a group of binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. What this means that if you convert any file in base64 you’d get a string output that you can then reconvert back to the file anytime. If we base64 encode the .pem files we would get a string output that we can then decode and get back our .pem files, meaning our env variables simply have to be the base64 string and our application should take it from there. The next step is converting our .pem files into base64.
CONVERTING FILE TO STRING
With the script above if you set the path correctly and run it you should get the base64 string representation of that file. In our case, the string representation of our pem files is what we are going to set in our environment variable. Over to the next step using these env variables in our application.
CONVERTING STRING TO FILE
Now to be able to use this in our Nodejs application we need to understand a few key things. When you try to read a file in Nodejs the function returns a buffer instance read from that file and since our DB connection is expecting a file we must create a buffer instance that would come from a base64 decode of our environment variable. makes sense? This is so that it still appears as a file to our ORM package (Which in this case is Knex.js).
From the file above the most important lines are 15,16 and 17 where the Buffer instance is passed to the values “ca”, “key” and “cert”. What is happening in that line is using our dotenv package (imported at line 4) it takes our env variables (which would be the base64 strings of our .pem files) and assigns them under process.env (so an env key “DB_SSL_CA” would be available as “process.env.DB_SSL_CA” in our application). With that understood these lines basically create a Buffer (hypothetical file) from the base64 decoded values of our env variables (which were already base64 encoded values of our .pem files).
That's it..., We are done here, ideally, any errors or issues you might have may come from your env variables or your base64 decoding/encoding steps so the first bet would be to test those steps if you encounter any issues following my guide. Note: This approach can be reproduced for other files and not just .pem files but be careful though, as the larger the files the harder/longer the base64 operations on it would take. Happy Coding.